Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security:...

83
Mini-Lesson M6, Scripts & Source Code/ Page 1 Enhancing Database Security: Concepts and Tools for the DBA * Scripts & Source Code Peter J. Magee, CDA SQRIBE Technologies Passwords in Command Lines Fix for ctxctl script to eliminate appearance of CTXSYS password in command line. 1. Copy ctxctl to ctxctl.secure 2. In ctxctl.secure, replace the following command line (line 312): $exe -user $username/$password -personality $mask >> /dev/null & with these lines: CTX_PASS=$username/$password export CTX_PASS $ORACLE_HOME/bin/ctxsecure $exe $mask & CTX_PASS= export CTX_PASS 3. Create a script called ctxsecure in the $ORACLE_HOME/bin directory: # # File: ctxsecure # Location: $ORACLE_HOME/bin # # This file calls the specified ConText executable application, # but prevents the CTXSYS userid and password from appearing in # the command line. This prevents the user id and password from # being visible to a "ps -ef" command. # # Inputs: $1 Executable ConText file name # $2 Personality flag for server # $CTX_PASS An environment variable holding # the CTXSYS user id and password # $1 -personality $2 >> /dev/null <<CTXEND ${CTX_PASS} CTXEND

Transcript of Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security:...

Page 1: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 1

Enhancing Database Security:

Concepts and Tools for the DBA * Scripts & Source Code

Peter J. Magee, CDA

SQRIBE Technologies

Passwords in Command Lines

Fix for ctxctl script to eliminate appearance of CTXSYS password in command line.

1. Copy ctxctl to ctxctl.secure

2. In ctxctl.secure, replace the following command line (line 312):

$exe -user $username/$password -personality $mask >> /dev/null &

with these lines:

CTX_PASS=$username/$password

export CTX_PASS

$ORACLE_HOME/bin/ctxsecure $exe $mask &

CTX_PASS=

export CTX_PASS

3. Create a script called ctxsecure in the $ORACLE_HOME/bin directory:

#

# File: ctxsecure

# Location: $ORACLE_HOME/bin

#

# This file calls the specified ConText executable application,

# but prevents the CTXSYS userid and password from appearing in

# the command line. This prevents the user id and password from

# being visible to a "ps -ef" command.

#

# Inputs: $1 Executable ConText file name

# $2 Personality flag for server

# $CTX_PASS An environment variable holding

# the CTXSYS user id and password

#

$1 -personality $2 >> /dev/null <<CTXEND

${CTX_PASS}

CTXEND

Page 2: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 2

Note: do not place the characteristic $!/bin/sh in the first line of ctxsecure. If a new shell is opened, $CTX_PASS

can not be found. ctxsecure should run in the same shell as ctxctl.secure.

Once these steps are complete, use ctxctl.secure the same as you would use ctxctl. An additional process will be

generated by ctxctl.secure for each ConText server, so "ps -ef" output would look something like this:

oracle 1397 1395 $ORACLE_HOME/bin/ctxsrv -personality LQ

oracle 1395 1 /bin/sh ctxctl.secure

Initialization Parameters

Select values for security related initialization parameters from the data dictionary.

select * from v$parameter

where name in ('audit_trail', ‘db_encrypt_login’, 'resource_limit', 'remote_os_auth',

'remote_os_roles', 'os_roles', 'utl_file_dir');

SQL*Net Firewalls

A sample protocol.ora file, located in the $ORACLE_HOME/network/admin directory:

tcp.validnode_checking = yes

tcp.invited_nodes = (drummer.us.com,

139.185.5.73,

139.185.5.111)

Application Users (OPS$ Users)

Identify externally authenticated user accounts.

select username, password from dba_users where password='EXTERNAL';

System Privileges

Identify system privileges granted to users other than SYS, SYSTEM, or DBSNMP.

select p.grantee, p.privilege

from dba_sys_privs p, dba_users u

where (u.username = p.grantee or p.grantee='PUBLIC') and

p.grantee not in ('SYS','SYSTEM','DBSNMP');

Identify system privileges granted to roles other than DBA, RESOURCE, IMP_FULL_DATABASE,

EXP_FULL_DATABASE, CONNECT, and SNMPAGENT.

select p.grantee, p.privilege

from dba_sys_privs p, dba_roles r

where r.role = p.grantee and r.role not in

('DBA','RESOURCE','IMP_FULL_DATABASE','EXP_FULL_DATABASE',

'CONNECT','SNMPAGENT');

Page 3: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 3

The following System Privileges should only be granted to administrators, never application users:

ANALYZE ANY ALTER ANY ROLE SELECT ANY TABLE

AUDIT ANY DROP ANY ROLE INSERT ANY TABLE

AUDIT SYSTEM GRANT ANY ROLE UPDATE ANY TABLE

ALTER ANY CLUSTER DROP ROLLBACK

SEGMENT

DELETE ANY TABLE

DROP ANY CLUSTER RESTRICTED SESSION TABLESPACE

ALTER DATABASE CREATE ANY SEQUENCE MANAGE TABLESPACE

CREATE ANY INDEX ALTER ANY SEQUENCE UNLIMITED TABLESPACE

ALTER ANY INDEX DROP ANY SEQUENCE FORCE TRANSACTION

DROP ANY INDEX SELECT ANY SEQUENCE FORCE ANY TRANSACTION

GRANT ANY PRIVILEGE ALTER ANY SNAPSHOT CREATE ANY TRIGGER

CREATE ANY PROCEDURE DROP ANY SNAPSHOT ALTER ANY TRIGGER

ALTER ANY PROCEDURE CREATE ANY SYNONYM DROP ANY TRIGGER

DROP ANY PROCEDURE DROP ANY SYNONYM BECOME USER

EXECUTE ANY PROCEDURE ALTER SYSTEM CREATE ANY VIEW

CREATE PROFILE CREATE ANY TABLE DROP ANY VIEW

ALTER PROFILE ALTER ANY TABLE CREATE DATABASE LINK

DROP PROFILE BACKUP ANY TABLE CREATE PUBLIC DATABASE

LINK

ALTER RESOURCE COST DROP ANY TABLE DROP PUBLIC DATABASE LINK

DROP PUBLIC DATABASE LINK LOCK ANY TABLE CREATE PUBLIC SYNONYM

DROP PUBLIC SYNONYM COMMENT ANY TABLE DROP PUBLIC SYNONYM

Object Privileges

Identify users other than SYS and SYSTEM that have been granted ALTER or REFERENCES priveleges.

select t.grantee, t.owner || '.' || t.table_name, t.privilege

from dba_tab_privs t, dba_users u

where (u.username = t.grantee or t.grantee = 'PUBLIC')

and t.privilege in ('ALTER','REFERENCES') and

t.grantee not in ('SYS','SYSTEM');

Identify roles other than DBA, RESOURCE, IMP_FULL_DATABASE, EXP_FULL_DATABASE, and

CONNECT that have been granted ALTER or REFERENCES privileges.

select t.grantee, t.owner || '.' || t.table_name, t.privilege

from dba_tab_privs t, dba_roles r

where r.role = t.grantee and t.privilege in ('ALTER','REFERENCES')

and r.role not in ('DBA','RESOURCE','IMP_FULL_DATABASE',

'EXP_FULL_DATABASE','CONNECT');

Administration Privileges

Identify users other than SYS and SYSTEM that have ADMIN privileges on system and object privileges.

Page 4: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 4

select p.grantee, p.privilege, p.admin_option

from dba_sys_privs p, dba_users u

where (u.username = p.grantee or p.grantee='PUBLIC') and

p.admin_option='YES' and p.grantee not in ('SYS','SYSTEM');

Identify users other than SYS and SYSTEM that have ADMIN privileges on the Oracle default roles.

select r.grantee, r.granted_role, r.admin_option

from dba_role_privs r, dba_users u

where u.username = r.grantee and r.granted_role in

('DBA','RESOURCE','IMP_FULL_DATABASE','EXP_FULL_DATABASE',

'CONNECT','SNMPAGENT') and r.admin_option='YES' and

r.grantee not in ('SYS','SYSTEM');

Predefined Roles

Identify users that have been granted one of the Oracle default roles.

select r.grantee, r.granted_role

from dba_role_privs r

where r.granted_role in ('DBA','EXP_FULL_DATABASE',

'IMP_FULL_DATABASE','OSOPER','OSDBA') and

r.grantee not in ('SYS','SYSTEM','DBA');

Application Roles

Identify application roles and their properties.

select r.role, r.password_required from dba_roles r

where r.role not in ('DBA','RESOURCE','IMP_FULL_DATABASE',

'EXP_FULL_DATABASE','CONNECT','SNMPAGENT');

Identify users that have been assigned to application roles.

select r.grantee, r.granted_role, r.admin_option

from dba_role_privs r, dba_users u

where u.username = r.grantee and

r.granted_role not in ('DBA','RESOURCE','IMP_FULL_DATABASE',

'EXP_FULL_DATABASE','CONNECT','SNMPAGENT');

User Profiles

Identify the idle time limit for each database user.

select u.username, p.limit

from dba_users u, dba_profiles p

where u.profile = p.profile and p.resource_name='IDLE_TIME';

Alter the profile idle time.

alter profile [profile name] limit idle_time [# minutes];

Page 5: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 5

Oracle7 Profiles

Lock a User Account: Alter encrypted password to all lowercase; Oracle can’t translate so account is disabled

alter user [username] identified by values ‘disabled’;

Oracle8 Profiles

User Profile Creation:

Create a profile that will do the following:

· The user will be timed out (disconnected) after 15 minutes of idle time.

· The account will be locked after 3 failed logins.

· The account can only be unlocked by the DBA.

· The user has 3 grace logins to change their password after expiration.

· The user cannot repeat passwords until they have been changed at least 10 times.

· The password expires after 90 days.

· The stored procedure verify_password will be used to verify password complexity.

To create the profile execute the following script.

CREATE PROFILE APP_USER LIMIT

IDLE_TIME 15

FAILED_LOGIN_ATTEMPTS 3

ACCOUNT_LOCK_TIME UNLIMITED

PASSWORD_GRACE_TIME 3

PASSWORD_REUSE_MAX 10

PASSWORD_LIFE_TIME 90

PASSWORD_VERIFY_FUNCTION verify_password;

Once the profile is created, it is assigned to the user with the ALTER USER command:

ALTER USER username PROFILE app_user;

Password Varification Function: based on sample function in Oracle documentation, but more strict.

CREATE OR REPLACE FUNCTION verify_function

(username varchar2,

password varchar2,

old_password varchar2)

RETURN boolean IS

n boolean;

m integer;

differ integer;

isdigit boolean;

Page 6: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 6

ischar boolean;

ispunct boolean;

digitarray varchar2(20);

punctarray varchar2(25);

chararray varchar2(52);

BEGIN

digitarray:= '0123456789';

chararray:= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

punctarray:='!"#$%&()``*+,-/:;<=>?_';

--Check if the password is same as the username

IF password = username THEN

raise_application_error(-20001, 'Password same as user');

END IF;

--Check for the minimum length of the password (must be 6 or more)

IF length(password) < 6 THEN

raise_application_error(-20002, 'Password length less than 6');

END IF;

--Check if the password is too simple. A dictionary of words may be

--maintained and a check may be made so as not to allow the words

--that are too simple for the password.

IF NLS_LOWER(password) IN ('welcome', 'database', 'account', 'user',

'password', 'oracle', 'computer', 'abcd') THEN

raise_application_error(-20002, 'Password too simple');

END IF;

--Check if the password contains at least one letter and one digit

--

--1. Check for the digit

isdigit:=FALSE;

m := length(password);

FOR i IN 1..10 LOOP

FOR j IN 1..m LOOP

IF substr(password,j,1) = substr(digitarray,i,1) THEN

isdigit:=TRUE;

GOTO findchar;

END IF;

Page 7: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 7

END LOOP;

END LOOP;

IF isdigit = FALSE THEN

raise_application_error(-20003,’Password should contain at least one

digit, one character and one punctuation');

END IF;

--2. Check for the character

<<findchar>>

ischar:=FALSE;

FOR i IN 1..length(chararray) LOOP

FOR j IN 1..m LOOP

IF substr(password,j,1) = substr(chararray,i,1) THEN

ischar:=TRUE;

GOTO findpunct;

END IF;

END LOOP;

END LOOP;

IF ischar = FALSE THEN

raise_application_error(-20003,'Password should contain at least one

digit, one character and one punctuation');

END IF;

<<endsearch>>

--Check if the password differs from the previous password by at least

--3 letters

IF old_password = '' THEN

raise_application_error(-20004, 'Old password is null');

END IF;

--Everything is fine; return TRUE ;

differ := length(old_password) - length(password);

IF abs(differ) < 3 THEN

IF length(password) < length(old_password) THEN

m := length(password);

ELSE

m:= length(old_password);

END IF;

Page 8: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 8

differ := abs(differ);

FOR i IN 1..m LOOP

IF substr(password,i,1) != substr(old_password,i,1) THEN

differ := differ + 1;

END IF;

END LOOP;

IF differ < 3 THEN

raise_application_error(-20004, 'Password should differ by at \

least 3 characters');

END IF;

END IF;

--Everything is fine; return TRUE ;

RETURN(TRUE);

END;

Lock User Account:

alter user [username] account lock;

Statement Level Audits

Generate a list of all statement level audits.

select audit_option, success, failure from dba_stmt_audit_opts;

Enable minimum required statement level audits:

audit ALTER SYSTEM ;

audit INDEX ;

audit NOT EXISTS ;

audit SYSTEM GRANT ;

audit SYSTEM AUDIT ;

audit TABLE ;

audit TABLESPACE ;

audit USER ;

audit SESSION ;

audit RESTRICTED SESSION ;

Object Level Audits

Generate a list of all object level audits.

select owner, object_name, object_type from dba_obj_audit_opts where ren = '-/-';

Identify all audits on the audit trail table.

select owner || '.' || object_name, object_type,

alt || aud || com || del || gra || ind || ins ||

loc || ren || sel || upd || ref || exe

Page 9: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 9

from dba_obj_audit_opts

where owner like 'SYS%' and object_name='AUD$' and object_type='TABLE';

Set audit rename by default on all objects created after command:

audit rename on default;

Audit actions on the audit trail:

audit all on sys.aud$; or audit all on system.aud$; (if ownership has been changed)

Privilege Level Audits

Generate a list of all privilege level audits.

select privilege, success, failure from dba_priv_audit_opts;

Enable minimum required privilege level audits:

audit ANALYZE ANY ;

audit AUDIT ANY ;

audit AUDIT SYSTEM ;

audit ALTER ANY CLUSTER ;

audit DROP ANY CLUSTER ;

audit ALTER DATABASE ;

audit CREATE ANY INDEX ;

audit ALTER ANY INDEX ;

audit DROP ANY INDEX ;

audit GRANT ANY PRIVILEGE ;

audit CREATE ANY PROCEDURE ;

audit ALTER ANY PROCEDURE ;

audit DROP ANY PROCEDURE ;

audit EXECUTE ANY PROCEDURE ;

audit CREATE PROFILE ;

audit ALTER PROFILE ;

audit DROP PROFILE ;

audit ALTER RESOURCE COST ;

audit DROP PUBLIC DATABASE LINK ;

audit DROP PUBLIC SYNONYM ;

audit ALTER ANY ROLE ;

audit DROP ANY ROLE ;

audit GRANT ANY ROLE ;

audit DROP ROLLBACK SEGMENT ;

audit CREATE ANY SEQUENCE ;

audit ALTER ANY SEQUENCE ;

audit DROP ANY SEQUENCE ;

audit SELECT ANY SEQUENCE ;

audit ALTER ANY SNAPSHOT ;

Page 10: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 10

audit DROP ANY SNAPSHOT ;

audit CREATE ANY SYNONYM ;

audit DROP ANY SYNONYM ;

audit CREATE ANY TABLE ;

audit ALTER ANY TABLE ;

audit BACKUP ANY TABLE ;

audit DROP ANY TABLE ;

audit LOCK ANY TABLE ;

audit COMMENT ANY TABLE ;

audit SELECT ANY TABLE ;

audit INSERT ANY TABLE ;

audit UPDATE ANY TABLE ;

audit DELETE ANY TABLE ;

audit MANAGE TABLESPACE ;

audit UNLIMITED TABLESPACE ;

audit FORCE TRANSACTION ;

audit FORCE ANY TRANSACTION ;

audit CREATE ANY TRIGGER ;

audit ALTER ANY TRIGGER ;

audit DROP ANY TRIGGER ;

audit CREATE USER ;

audit BECOME USER ;

audit ALTER USER ;

audit DROP USER ;

audit CREATE ANY VIEW ;

audit DROP ANY VIEW ;

audit CREATE PUBLIC DATABASE LINK ;

audit DROP PUBLIC DATABASE LINK ;

audit CREATE PUBLIC SYNONYM ;

audit DROP PUBLIC SYNONYM ;

audit CREATE DATABASE LINK ;

Audit Trail Maintenance

Set the following init.ora parameters and restart the database to initialize the Oracle Job Queue:

JOB_QUEUE_PROCESSES = 1

JOB_QUEUE_INTERVAL = 30

Create the following stored procedure as SYSTEM through Server Manager or SQL*Plus:

Oracle7 Version:

CREATE PROCEDURE TRIM_AUDIT_TRAIL AS

BEGIN

Page 11: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 11

DELETE FROM SYS.AUD$ WHERE TIMESTAMP < TRUNC(SYSDATE-7);

COMMIT;

END TRIM_AUDIT_TRAIL;

Oracle8 Version:

CREATE PROCEDURE TRIM_AUDIT_TRAIL AS

BEGIN

DELETE FROM SYS.AUD$ WHERE TIMESTAMP# < TRUNC(SYSDATE-7);

COMMIT;

END TRIM_AUDIT_TRAIL;

Set the job to run once per day at midnight using Server Manager or SQL*Plus:

VARIABLE JOBNUM NUMBER;

BEGIN

DBMS_JOB.SUBMIT(:JOBNUM,'SYSTEM.TRIM_AUDIT_TRAIL; ',

TRUNC(SYSDATE+1),'TRUNC(SYSDATE+1)');

END;

Check on the status of the job using the DBA_JOBS or USER_JOBS views.

Eagle

Original Eagle DDL (by Jay M ehta, IOUG-A Select M agazine, April, 1997):

REM Name: eddl.sql

REM Description: Creates Objects(Tables/Indexes) in USERS and USERS_IDX tablespace

REM Usage: Run this script from SQL*Plus, Use Eagle Oracle account

REM

CREATE TABLE WATCH (

WATCH_ID VARCHAR2(12) NOT NULL,

NAME VARCHAR2(30) NOT NULL,

PREPARE1_CLAUSE VARCHAR2(512) NULL,

PREPARE2_CLAUSE VARCHAR2(512) NULL,

INSERT_CLAUSE VARCHAR2(512) NOT NULL,

SELECT_CLAUSE VARCHAR2(512) NOT NULL,

WHERE_CLAUSE VARCHAR2(512) NULL,

CLOSE1_CLAUSE VARCHAR2(512) NULL,

CLOSE2_CLAUSE VARCHAR2(512) NULL,

CONSTRAINT WATCK_PK

PRIMARY KEY (WATCH_ID)

USING INDEX TABLESPACE USERS_IDX

STORAGE(INITIAL 16K NEXT 16K PCTINCREASE 0)

) TABLESPACE USERS

STORAGE (INITIAL 16K NEXT 16K PCTINCREASE 0) ;

Page 12: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 12

CREATE TABLE DATABASE (

DB_ID VARCHAR2(12) NOT NULL,

NAME VARCHAR2(30) NOT NULL,

DB_LINK VARCHAR2(30) NOT NULL,

CONSTRAINT DATABASE_PK

PRIMARY KEY (DB_ID)

USING INDEX TABLESPACE USERS_IDX

STORAGE (INITIAL 16K NEXT 16K PCTINCREASE 0)

) TABLESPACE USERS

STORAGE (INITIAL 16K NEXT 16K PCTINCREASE 0) ;

CREATE TABLE DB_WATCH (

DB_ID VARCHAR2(12) NOT NULL,

WATCH_ID VARCHAR2(12) NOT NULL,

ACTIVE_YN VARCHAR2(1),

CONSTRAINT DB_WATCH_PK

PRIMARY KEY (DB_ID, WATCH_ID)

USING INDEX TABLESPACE USERS_IDX

STORAGE(INITIAL 16K NEXT 16K PCTINCREASE 0),

CONSTRAINT DB_WATCH_FK1

FOREIGN KEY (DB_ID)

REFERENCES DATABASE (DB_ID),

CONSTRAINT DB_WATCH_FK2

FOREIGN KEY (WATCH_ID)

REFERENCES WATCH (WATCH_ID)

) TABLESPACE USERS

STORAGE ( INITIAL 16K NEXT 16K PCTINCREASE 0) ;

CREATE TABLE DB_WATCH_RESULT(

DB_ID VARCHAR2(12) NOT NULL,

WATCH_ID VARCHAR2(12) NOT NULL,

RUN_TIME DATE NOT NULL,

PARAMETER VARCHAR2(256) NULL,

VALUE NUMBER(12,2) NOT NULL,

CONSTRAINT DB_WATCH_RESULT_FK

FOREIGN KEY (DB_ID,WATCH_ID)

REFERENCES DB_WATCH(DB_ID, WATCH_ID)

) TABLESPACE USERS

STORAGE ( INITIAL 16K NEXT 16K PCTINCREASE 0) ;

Page 13: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 13

Note: The sizes of the prepare, insert, select, where, and close clause fields in the WATCH table have been

increased from the original 256 characters to 512 characters to accommodate the various watches described

below. You may need to increase them further to support your own custom watches. You may also need to alter

storage parameters to fit your particular system.

Original Eagle PL/SQL Engine (by Jay M ehta, IOUG-A Select M agazine, April, 1997):

REM

REM Name: eplsql.sql

REM Description: Create PL/SQL procudure that executes active watched

REM Usage: Run from SQL*Plus, Use Eagle account

REM

CREATE OR REPLACE PROCEDURE EXECUTE_DB_WATCH

AS

CURSOR C_DB_WATCH IS

SELECT DB_ID, WATCH_ID, ACTIVE_YN

FROM DB_WATCH ;

db_watch_rec DB_WATCH%ROWTYPE ;

watch_rec WATCH%ROWTYPE ;

database_rec DATABASE%ROWTYPE ;

sql_stmt VARCHAR2(1000) ;

ret_val INTEGER ;

cursor_id INTEGER ;

c_get_data INTEGER ;

temp_clause VARCHAR2(256) ;

BEGIN

OPEN C_DB_WATCH;

LOOP

FETCH C_DB_WATCH INTO db_watch_rec;

EXIT WHEN C_DB_WATCH%NOTFOUND ;

IF db_watch_rec.active_yn = 'Y' THEN

SELECT *

INTO watch_rec

FROM WATCH

WHERE WATCH_ID = db_watch_rec.watch_id ;

/* fetch database record */

SELECT *

INTO database_rec

FROM DATABASE

WHERE DB_ID = db_watch_rec.db_id ;

watch_rec.select_clause := REPLACE(watch_rec.select_clause,

'<DB_ID>',database_rec.db_id);

Page 14: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 14

watch_rec.select_clause := REPLACE(watch_rec.select_clause,

'<DB_LINK>',database_rec.db_link);

sql_stmt := watch_rec.insert_clause ||

watch_rec.select_clause ||

watch_rec.where_clause;

IF watch_rec.prepare1_clause IS NOT NULL THEN

watch_rec.prepare1_clause := REPLACE(watch_rec.prepare1_clause,

'<DB_LINK>',database_rec.db_link);

cursor_id := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_id,watch_rec.prepare1_clause,DBMS_SQL.V7);

ret_val := DBMS_SQL.EXECUTE(cursor_id) ;

DBMS_SQL.CLOSE_CURSOR(cursor_id);

END IF;

IF watch_rec.prepare2_clause IS NOT NULL THEN

watch_rec.prepare2_clause := REPLACE(watch_rec.prepare2_clause,

'<DB_LINK>',database_rec.db_link);

cursor_id := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_id,watch_rec.prepare2_clause,DBMS_SQL.V7);

ret_val := DBMS_SQL.EXECUTE(cursor_id) ;

DBMS_SQL.CLOSE_CURSOR(cursor_id);

END IF;

c_get_data := DBMS_SQL.OPEN_CURSOR ;

DBMS_SQL.PARSE(c_get_data,sql_stmt,DBMS_SQL.V7) ;

ret_val := DBMS_SQL.EXECUTE(c_get_data) ;

DBMS_SQL.CLOSE_CURSOR(c_get_data) ;

IF watch_rec.close1_clause IS NOT NULL THEN

cursor_id := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_id,watch_rec.close1_clause,DBMS_SQL.V7);

ret_val := DBMS_SQL.EXECUTE(cursor_id) ;

DBMS_SQL.CLOSE_CURSOR(cursor_id);

END IF;

IF watch_rec.close2_clause IS NOT NULL THEN

cursor_id := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_id,watch_rec.close2_clause,DBMS_SQL.V7);

ret_val := DBMS_SQL.EXECUTE(cursor_id) ;

DBMS_SQL.CLOSE_CURSOR(cursor_id);

END IF;

END IF;

Page 15: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 15

END LOOP;

END ;

/

Eagle Enhanced

Replacement PL/SQL Engine for Eagle:

create or replace package eagle as

/* procedure run is the top-level procedure that calls all others. A DBA can specify a

specific database for monitoring, or let the procedure default to all databases. */

procedure run (dbid in varchar2 default '%');

/* procedure sqlexec opens a cursor for each SQL command and executes the command. */

procedure sqlexec (querystr in varchar2, dbid in varchar2, dblink in varchar2);

/* function sqlinit replaces the <DB_ID> and <DB_LINK> keywords in each SQL command

with the appropriate database name and database link name. */

function sqlinit (querystr in varchar2, dbid in varchar2, dblink in varchar2) return varchar2;

end eagle;

/

create or replace package body eagle as

no_connection EXCEPTION;

PRAGMA EXCEPTION_INIT(no_connection, -12203);

procedure run (dbid in varchar2 default '%') is

cursor c_db_watch (db varchar2) is

select db_id, watch_id, active_yn

from db_watch where db_id like db order by db_id;

db_watch_rec db_watch%ROWTYPE;

watch_rec watch%ROWTYPE;

database_rec database%ROWTYPE;

sqltext varchar2(2000);

begin

/* Open the list of database watches for the specified database */

open c_db_watch(dbid);

loop

/* Get the next database watch record, exit when no more records found */

fetch c_db_watch into db_watch_rec;

exit when c_db_watch%NOTFOUND;

Page 16: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 16

/* If the watch is active, then execute */

if db_watch_rec.active_yn = 'Y' then

/* Get the details for the watch and database */

select * into watch_rec from watch where watch_id=db_watch_rec.watch_id;

select * into database_rec from database where db_id=db_watch_rec.db_id;

/* Execute the prepare clauses for the watch */

sqlexec (watch_rec.prepare1_clause,database_rec.db_id,database_rec.db_link);

sqlexec (watch_rec.prepare2_clause,database_rec.db_id,database_rec.db_link);

/* Execute the watch insert as select command */

sqltext := watch_rec.insert_clause || watch_rec.select_clause || watch_rec.where_clause;

sqlexec (sqltext,database_rec.db_id,database_rec.db_link);

/* Execute the close clauses for the watch */

sqlexec (watch_rec.close1_clause,database_rec.db_id,database_rec.db_link);

sqlexec (watch_rec.close2_clause,database_rec.db_id,database_rec.db_link);

end if;

end loop;

end run;

procedure sqlexec (querystr in varchar2, dbid in varchar2, dblink in varchar2) is

sqltext varchar2(2000);

ret_val integer;

cursor_id integer;

begin

/* Determine if this SQL command is null */

if querystr is not null then

/* Initialize the SQL command by replacing keywords with values for db_id and db_link */

sqltext := sqlinit (querystr, dbid, dblink);

/* Open and execute the cursor for the SQL command */

cursor_id := dbms_sql.open_cursor;

dbms_sql.parse(cursor_id,sqltext,dbms_sql.v7);

ret_val := dbms_sql.execute(cursor_id) ;

/* Close the cursor and exit */

Page 17: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 17

dbms_sql.close_cursor(cursor_id);

end if;

exception

/* When a connection to target database is not found, proceed to next watch */

when no_connection then

return;

end sqlexec;

function sqlinit (querystr in varchar2, dbid in varchar2, dblink in varchar2) return varchar2 is

sqltext varchar2(2000);

begin

sqltext := querystr;

sqltext := replace(sqltext,'<DB_ID>',dbid);

sqltext := replace(sqltext,'<DB_LINK>',dblink);

return sqltext;

end sqlinit;

end eagle;

/

Eagle Extended

The following scripts can be used to extend Eagle to collect audit trail information.

AUDIT_TRAIL DDL for Eagle in Oracle7 AUDIT_TRAIL DDL for Eagle in Oracle8CREATE TABLE AUDIT_TRAIL

(DB_ID VARCHAR2(12) NOT NULL,

SESSIONID NUMBER NOT NULL,

ENTRYID NUMBER NOT NULL,

STATEMENT NUMBER NOT NULL,

TIMESTAMP# DATE NOT NULL,

USERID VARCHAR2(30) NULL,

USERHOST VARCHAR2(255) NULL,

TERMINAL VARCHAR2(255) NULL,

ACTION# NUMBER NOT NULL,

RETURNCODE NUMBER NOT NULL,

OBJ$CREATOR VARCHAR2(30) NULL,

OBJ$NAME VARCHAR2(128) NULL,

AUTH$PRIVILEGES VARCHAR2(16) NULL,

AUTH$GRANTEE VARCHAR2(30) NULL,

NEW$OWNER VARCHAR2(30) NULL,

NEW$NAME VARCHAR2(128) NULL,

SES$ACTIONS VARCHAR2(19) NULL,

CREATE TABLE AUDIT_TRAIL

(DB_ID VARCHAR2(12) NOT NULL,

SESSIONID NUMBER NOT NULL,

ENTRYID NUMBER NOT NULL,

STATEMENT NUMBER NOT NULL,

TIMESTAMP# DATE NOT NULL,

USERID VARCHAR2(30) NULL,

USERHOST VARCHAR2(255) NULL,

TERMINAL VARCHAR2(255) NULL,

ACTION# NUMBER NOT NULL,

RETURNCODE NUMBER NOT NULL,

OBJ$CREATOR VARCHAR2(30) NULL,

OBJ$NAME VARCHAR2(128) NULL,

AUTH$PRIVILEGES VARCHAR2(16) NULL,

AUTH$GRANTEE VARCHAR2(30) NULL,

NEW$OWNER VARCHAR2(30) NULL,

NEW$NAME VARCHAR2(128) NULL,

SES$ACTIONS VARCHAR2(19) NULL,

Page 18: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 18

SES$TID NUMBER NULL,

LOGOFF$LREAD NUMBER NULL,

LOGOFF$PREAD NUMBER NULL,

LOGOFF$LWRITE NUMBER NULL,

LOGOFF$DEAD NUMBER NULL,

LOGOFF$TIME DATE NULL,

COMMENT$TEXT VARCHAR2(2000) NULL,

SPARE1 VARCHAR2(255) NULL,

SPARE2 NUMBER NULL,

OBJ$LABEL RAW(255) NULL,

SES$LABEL RAW(255) NULL,

PRIV$USED NUMBER NULL

)

STORAGE ( INITIAL 1M NEXT 1M MINEXTENTS 1

PCTINCREASE 0)

TABLESPACE "DBAUDIT";

SES$TID NUMBER NULL,

LOGOFF$LREAD NUMBER NULL,

LOGOFF$PREAD NUMBER NULL,

LOGOFF$LWRITE NUMBER NULL,

LOGOFF$DEAD NUMBER NULL,

LOGOFF$TIME DATE NULL,

COMMENT$TEXT VARCHAR2(4000) NULL,

SPARE1 VARCHAR2(255) NULL,

SPARE2 NUMBER NULL,

OBJ$LABEL RAW(255) NULL,

SES$LABEL RAW(255) NULL,

PRIV$USED NUMBER NULL

)

STORAGE ( INITIAL 1M NEXT 1M MINEXTENTS 1

PCTINCREASE 0)

TABLESPACE "DBAUDIT";

Notes:

· The COMMENT$TEXT field from an Oracle8

database must be trimmed from varchar2(4000) to

varchar2(2000).

· The SES$ACTIONS field was expanded from

varchar2(16) to varchar2(19) to accommodate

Oracle8 values.

· The TIMESTAMP and ACTION fields have been

renamed, adding a '#' character to the end of each.

Notes:

· All data from Oracle7 and Oracle8 audit trails can

be stored in this table without being trimmed or

altered.

· The USERHOST field was expanded from

varchar2(128) to varchar2(255) to accommodate

Oracle7 values.

Copy the AUDIT_ACTIONS table into the Eagle schema for use in reports and views:

CREATE TABLE EAGLE.AUDIT_ACTIONS

TABLESPACE USERS

AS SELECT * FROM SYS.AUDIT_ACTIONS;

There are three (3) different watches that can be used to collect audit trail data, depending on the version numbers

of the Eagle database and the target database. Each watch will do the following:

· Copy all audit entries from AUD$ in the target database to AUDIT_TRAIL in the Eagle database, adding the

DB_ID field as a source identifier. Only those entries made since the last time Eagle has run will be copied

(no duplicates).

· Automatically delete any entries more than 365 days old.

Use the following table to determine which audit watch to use for your systems.

Page 19: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 19

Target Database

Database Version Oracle7 Oracle8

Eagle DatabaseOracle7 AUDIT_7_TO _8 AUDIT_8_TO _7

Oracle8 AUDIT_7_TO _8 AUDIT_TRAIL

AUDIT_TRAIL W atch SQL: This watch can be used when both the Eagle and target databases are both Oracle8

insert into watch

(watch_id, name,

prepare1_clause,

insert_clause,

select_clause,

where_clause,

close1_clause)

values

('AUDIT_TRAIL','Database Audit Trail',

'delete from audit_trail where db_id=''<DB_ID>'' and timestamp < (sysdate-365)',

'insert into audit_trail ',

'select ''<DB_ID>'', a.* from sys.aud$ a ',

'where a.timestamp > (select nvl(max(timestamp),sysdate-1) from audit_trail where

db_id=''<DB_ID>'')',

'commit');

AUDIT_7_TO_8 Watch DDL: This watch is used when the target database is Oracle7 (the Eagle database can

be either Oracle7 or Oracle8)

insert into watch

(watch_id, name,

prepare1_clause,

prepare2_clause,

insert_clause,

select_clause,

where_clause,

close1_clause,

close2_clause)

values

('AUDIT_7_TO_8','Database Audit Trail (Oracle7)',

'delete from audit_trail where db_id=''<DB_ID>'' and timestamp < (sysdate-365)',

'CREATE OR REPLACE VIEW AUD$_V8 AS

SELECT

SESSIONID, ENTRYID, STATEMENT, TIMESTAMP TIMESTAMP#, USERID,

USERHOST, TERMINAL, ACTION ACTION#, RETURNCODE, OBJ$CREATOR,

Page 20: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 20

OBJ$NAME, AUTH$PRIVILEGES, AUTH$GRANTEE, NEW$OWNER, NEW$NAME,

SES$ACTIONS, SES$TID, LOGOFF$LREAD, LOGOFF$PREAD, LOGOFF$LWRITE,

LOGOFF$DEAD, LOGOFF$TIME, COMMENT$TEXT, SPARE1, SPARE2, OBJ$LABEL,

SES$LABEL, PRIV$USED

FROM SYS.AUD$@<DB_LINK>',

'insert into audit_trail ',

'select ''<DB_ID>'', a.* from aud$_v8 a ',

'where a.timestamp > (select nvl(max(timestamp),sysdate-1) from audit_trail where

db_id=''<DB_ID>'')',

'commit',

'drop view aud$_v8');

AUDIT_8_TO_7 Watch DDL: This watch is used when the Eagle database is in Oracle7 and the target database

is Oracle8

insert into watch

(watch_id, name,

prepare1_clause,

prepare2_clause,

insert_clause,

select_clause,

where_clause,

close1_clause,

close2_clause)

values

('AUDIT_8_TO_7','Database Audit Trail (Oracle8)',

'delete from audit_trail where db_id=''<DB_ID>'' and timestamp < (sysdate-365)',

'CREATE OR REPLACE VIEW AUD$_V7 AS

SELECT

SESSIONID, ENTRYID, STATEMENT, TIMESTAMP#, USERID,

USERHOST, TERMINAL, ACTION#, RETURNCODE, OBJ$CREATOR,

OBJ$NAME, AUTH$PRIVILEGES, AUTH$GRANTEE, NEW$OWNER, NEW$NAME,

SES$ACTIONS, SES$TID, LOGOFF$LREAD, LOGOFF$PREAD, LOGOFF$LWRITE,

LOGOFF$DEAD, LOGOFF$TIME, SUBSTR(COMMENT$TEXT,1,2000) COMMENT$TEXT,

SPARE1, SPARE2, OBJ$LABEL, SES$LABEL, PRIV$USED

FROM SYS.AUD$@<DB_LINK>',

'insert into audit_trail ',

'select ''<DB_ID>'', a.* from aud$_v7 a ',

'where a.timestamp > (select nvl(max(timestamp),sysdate-1) from audit_trail where

db_id=''<DB_ID>'')',

'commit',

'drop view aud$_v7');

Page 21: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 21

EAGLE_AUDIT_TRAIL VIEW DDL:

create or replace view eagle_audit_trail as

select db_id /* DB_ID */,

spare1 /* OS_USERNAME */,

userid /* USERNAME */,

userhost /* USERHOST */,

terminal /* TERMINAL */,

timestamp# /* TIMESTAMP */,

obj$creator /* OWNER */,

obj$name /* OBJECT_NAME */,

aud.action# /* ACTION */,

act.name /* ACTION_NAME */,

new$owner /* NEW_OWNER */,

new$name /* NEW_NAME */,

decode(aud.action#,

108 /* grant sys_priv */, null,

109 /* revoke sys_priv */, null,

114 /* grant role */, null,

115 /* revoke role */, null,

auth$privileges)

/* OBJ_PRIVILEGE */,

decode(aud.action#,

108 /* grant sys_priv */, spm.name,

109 /* revoke sys_priv */, spm.name,

null)

/* SYS_PRIVILEGE */,

decode(aud.action#,

108 /* grant sys_priv */, substr(auth$privileges,1,1),

109 /* revoke sys_priv */, substr(auth$privileges,1,1),

114 /* grant role */, substr(auth$privileges,1,1),

115 /* revoke role */, substr(auth$privileges,1,1),

null)

/* ADMIN_OPTION */,

auth$grantee /* GRANTEE */,

decode(aud.action#,

104 /* audit */, aom.name,

105 /* noaudit */, aom.name,

null)

/* AUDIT_OPTION */,

ses$actions /* SES_ACTIONS */,

Page 22: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 22

logoff$time /* LOGOFF_TIME */,

logoff$lread /* LOGOFF_LREAD */,

logoff$pread /* LOGOFF_PREAD */,

logoff$lwrite /* LOGOFF_LWRITE */,

decode(aud.action#,

104 /* audit */, null,

105 /* noaudit */, null,

108 /* grant sys_priv */, null,

109 /* revoke sys_priv */, null,

114 /* grant role */, null,

115 /* revoke role */, null,

aud.logoff$dead)

/* LOGOFF_DLOCK */,

comment$text /* COMMENT_TEXT */,

sessionid /* SESSIONID */,

entryid /* ENTRYID */,

statement /* STATEMENTID */,

returncode /* RETURNCODE */,

spx.name /* PRIVILEGE */,

rawtolab(obj$label) /* OBJECT_LABEL */,

rawtolab(ses$label) /* SESSION_LABEL */

from eagle.audit_trail aud, sys.system_privilege_map spm, sys.system_privilege_map spx,

sys.STMT_AUDIT_OPTION_MAP aom, eagle.audit_actions act

where aud.action# = act.action (+)

and - aud.logoff$dead = spm.privilege (+)

and aud.logoff$dead = aom.option# (+)

and - aud.priv$used = spx.privilege (+);

EAGLE_AUDIT_SESSION VIEW DDL:

create or replace view eagle_audit_session as

select db_id, os_username, username, userhost, terminal, timestamp, action_name,

logoff_time, logoff_lread, logoff_pread, logoff_lwrite, logoff_dlock,

sessionid, returncode, session_label

from eagle_audit_trail

where action between 100 and 102;

EAGLE_AUDIT_OBJECT VIEW DDL:

create or replace view eagle_audit_object as

select DB_ID, OS_USERNAME, USERNAME, USERHOST, TERMINAL, TIMESTAMP,

OWNER, OBJ_NAME, ACTION_NAME, NEW_OWNER, NEW_NAME,

SES_ACTIONS, COMMENT_TEXT, SESSIONID, ENTRYID, STATEMENTID,

RETURNCODE, PRIV_USED, OBJECT_LABEL, SESSION_LABEL

Page 23: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 23

from eagle_audit_trail

where (action between 1 and 16)

or (action between 19 and 29)

or (action between 32 and 41)

or (action = 43)

or (action between 51 and 99)

or (action = 103)

or (action between 110 and 113)

or (action between 116 and 121)

or (action between 123 and 128);

EAGLE_AUDIT_STATEMENT VIEW DDL:

create or replace view eagle_audit_statement as

select DB_ID, OS_USERNAME, USERNAME, USERHOST, TERMINAL, TIMESTAMP,

OWNER, OBJ_NAME, ACTION_NAME, NEW_NAME,

OBJ_PRIVILEGE, SYS_PRIVILEGE, ADMIN_OPTION, GRANTEE, AUDIT_OPTION,

SES_ACTIONS, COMMENT_TEXT, SESSIONID, ENTRYID, STATEMENTID,

RETURNCODE, PRIV_USED, SESSION_LABEL

from eagle_audit_trail

where action in ( 17 /* GRANT OBJECT */,

18 /* REVOKE OBJECT */,

30 /* AUDIT OBJECT */,

31 /* NOAUDIT OBJECT */,

49 /* ALTER SYSTEM */,

104 /* SYSTEM AUDIT */,

105 /* SYSTEM NOAUDIT */,

106 /* AUDIT DEFAULT */,

107 /* NOAUDIT DEFAULT */,

108 /* SYSTEM GRANT */,

109 /* SYSTEM REVOKE */,

114 /* GRANT ROLE */,

115 /* REVOKE ROLE */ );

EAGLE_AUDIT_CLIENT_SESSION VIEW DDL:

create or replace view eagle_audit_client_session as

select db_id, os_username, username, userhost, terminal, timestamp,

action_name, logoff_time, logoff_lread, logoff_pread,

logoff_lwrite, logoff_dlock, sessionid, returncode,

comment_text, session_label,

substr(substr(comment_text,instr(comment_text,'HOST=',1)+5,

instr(comment_text,')',instr(comment_text,'HOST=',1)) -

(instr(comment_text,'HOST=',1)+5)),1,15) ip_address

Page 24: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 24

from eagle_audit_trail

where action between 100 and 102;

EAGLE_AUDIT_FAILED_SESSION VIEW DDL:

create or replace view eagle_audit_failed_session as

select db_id, os_username, username, userhost, terminal, timestamp,

action_name, sessionid, returncode, comment_text,

substr(substr(comment_text,instr(comment_text,'HOST=',1)+5,

instr(comment_text,')',instr(comment_text,'HOST=',1)) -

(instr(comment_text,'HOST=',1)+5)),1,15) ip_address

from eagle_audit_trail

where returncode in (1017,1005) and action between 100 and 102;

Audit Trail Reports

The following sample reports were designed using Oracle WebServer 2.0 and the PL/SQL Agent. The are

included only as an example of the types of reports that can be generated with the centralized audit trail data

collected by Eagle.

DBAUDIT PACKAGE DDL:

create or replace package dbaudit as

procedure query;

procedure report (rptcode in varchar2 default 'session', db_nm in varchar2 default 'ALL',

user_nm in varchar2, object_nm in varchar2, action_nm in varchar2,

code in varchar2, day in varchar2, month in varchar2, year in varchar2);

procedure auditrpt (rptcode in varchar2, db_name in varchar2, user_name in varchar2,

object_name in varchar2, action_name in varchar2, rt_code in varchar2,

webday in varchar2, webmonth in varchar2, webyear in varchar2);

procedure dataheader (rptcode in varchar2);

procedure datafooter;

procedure getdata (rptcode in varchar2, db_name in varchar2, user_name in varchar2,

object_name in varchar2, action_name in varchar2, rtcode in varchar2,

webday in varchar2, webmonth in varchar2, webyear in varchar2);

end;

create or replace package body dbaudit as

--

-- Procedure query presents the initial report request form

--

procedure query is

cursor dblist is

select distinct db_id from eagle.audit_trail order by db_id;

cursor userlist is

Page 25: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 25

select distinct userid from eagle.audit_trail order by userid;

cursor objlist is

select distinct obj$name from eagle.audit_trail order by obj$name;

cursor actionlist is

select name, action from sys.audit_actions order by name;

cursor codelist is

select distinct returncode from eagle.audit_trail order by returncode;

begin

htp.htmlOpen;

htp.headOpen;

htp.title('STATS Database Audit History');

htp.headClose;

htp.bodyOpen('','BGCOLOR="#000066" TEXT="#ffffe8" LINK="#ccffff" VLINK="#33ccff"

BACKGROUND="/images/back10.jpg"');

htp.header(1,'STATS Database Audit History');

htp.hr;

htp.formOpen('/webaudit/owa/dbaudit.report','POST');

htp.print('<B>Select Report Criteria:</B><P>');

htp.tableOpen;

--

htp.print('<TR><TD WIDTH="150">Select Audit Report:</TD><TD>');

htp.formRadio('rptcode','session','CHECKED');

htp.print('Session Audits ');

htp.formRadio('rptcode','object');

htp.print('Object/Statement Audits');

htp.print('</TD></TR>');

--

htp.print('<TR><TD WIDTH="150">Database Name:</TD><TD>');

htp.formSelectOpen('db_nm');

htp.formSelectOption('ALL','SELECTED','value="ALL"');

for dc in dblist loop

htp.formSelectOption(dc.db_id,'','value="'||dc.db_id||'"');

end loop;

htp.formSelectClose;

htp.print('</TD></TR>');

--

htp.print('<TR><TD WIDTH="150">Database User Name:</TD><TD>');

htp.formSelectOpen('user_nm');

htp.formSelectOption('ALL','SELECTED','value="ALL"');

for uc in userlist loop

htp.formSelectOption(uc.userid,'','value="'||uc.userid||'"');

Page 26: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 26

end loop;

htp.formSelectClose;

htp.print('</TD></TR>');

--

htp.print('<TR><TD WIDTH="150">Object Name:</TD><TD>');

htp.formSelectOpen('object_nm');

htp.formSelectOption('ALL','SELECTED','value="ALL"');

for oc in objlist loop

htp.formSelectOption(oc.obj$name,'','value="'||oc.obj$name||'"');

end loop;

htp.formSelectClose;

htp.print(' (Object/Statement Audits only)</TD></TR>');

--

htp.print('<TR><TD WIDTH="150">Action Name:</TD><TD>');

htp.formSelectOpen('action_nm');

htp.formSelectOption('ALL','SELECTED','value="ALL"');

for ac in actionlist loop

htp.formSelectOption(ac.name,'','value="'||ac.action||'"');

end loop;

htp.formSelectClose;

htp.print(' (Object/Statement Audits only)</TD></TR>');

--

htp.print('<TR><TD WIDTH="150">Return Code:</TD><TD>');

htp.formSelectOpen('code');

htp.formSelectOption('ALL','SELECTED','value="ALL"');

for rc in codelist loop

htp.formSelectOption(rc.returncode,'','value="'||rc.returncode||'"');

end loop;

htp.formSelectClose;

htp.print('</TD></TR>');

--

htp.print('<TR><TD WIDTH="150">Day:</TD><TD>');

htp.formSelectOpen('day');

htp.formSelectOption('ALL','SELECTED','value="ALL"');

for ctr in 1..31 loop

htp.formSelectOption(ctr,'','value="'||ctr||'"');

end loop;

htp.formSelectClose;

htp.print('</TD></TR>');

--

Page 27: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 27

htp.print('<TR><TD WIDTH="150">Month:</TD><TD>');

htp.formSelectOpen('month');

htp.formSelectOption('ALL','SELECTED','value="ALL"');

htp.formSelectOption('January','','value="January "');

htp.formSelectOption('February','','value="February "');

htp.formSelectOption('March','','value="March "');

htp.formSelectOption('April','','value="April "');

htp.formSelectOption('May','','value="May "');

htp.formSelectOption('June','','value="June "');

htp.formSelectOption('July','','value="July "');

htp.formSelectOption('August','','value="August "');

htp.formSelectOption('September','','value="September"');

htp.formSelectOption('October','','value="October "');

htp.formSelectOption('November','','value="November "');

htp.formSelectOption('December','','value="December "');

htp.formSelectClose;

htp.print('</TD></TR>');

--

htp.print('<TR><TD WIDTH="150">Year:</TD><TD>');

htp.formSelectOpen('year');

htp.formSelectOption('ALL','','value="ALL"');

htp.formSelectOption('1997','','value="1997"');

htp.formSelectOption('1998','SELECTED','value="1998"');

htp.formSelectClose;

htp.print('</TD></TR>');

--

htp.tableClose;

htp.para;

htp.formSubmit('','Submit');

htp.formReset('Reset');

htp.formClose;

--

htp.hr;

htp.print('<P><FONT SIZE=2><CITE>');

htp.anchor('/','<IMG BORDER=0 SRC="/images/home-b.jpg">');

htp.anchor('mailto:[email protected]','<IMG BORDER=0 SRC="/images/mail-b.jpg">');

htp.para;

htp.img('/images/tag1.gif','bottom','Generated by Oracle WebServer');

--

htp.bodyClose;

Page 28: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 28

htp.htmlClose;

end query;

--

-- Procedure report parses the initial report request and calls the specified

-- report procedure.

--

procedure report (rptcode in varchar2 default 'session', db_nm in varchar2 default 'ALL',

user_nm in varchar2, object_nm in varchar2, action_nm in varchar2,

code in varchar2, day in varchar2, month in varchar2, year in varchar2) is

header_text varchar2(50);

db_name varchar2(10);

user_name varchar2(32);

object_name varchar2(32);

action_name varchar2(64);

rtcode varchar2(10);

webday varchar2(3);

webmnth varchar2(20);

webyear varchar2(4);

begin

if db_nm = 'ALL' then

db_name := '%';

else

db_name := db_nm;

end if;

--

if user_nm = 'ALL' then

user_name := '%';

else

user_name := user_nm;

end if;

--

if object_nm = 'ALL' then

object_name := '%';

else

object_name := object_nm;

end if;

--

if action_nm = 'ALL' then

action_name := '%';

else

Page 29: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 29

action_name := action_nm;

end if;

--

if code = 'ALL' then

rtcode := '%';

else

rtcode := code;

end if;

--

webday := day;

if length(webday) < 2 then

webday := '0' || webday;

end if;

--

if webday = 'ALL' then

webday := '%';

end if;

--

if month = 'ALL' then

webmnth := '%';

else

webmnth := rtrim(month) || '%';

end if;

--

if year = 'ALL' then

webyear := '%';

else

webyear := year;

end if;

--

htp.htmlOpen;

htp.headOpen;

htp.title('STATS Database Audit History');

htp.headClose;

htp.bodyOpen('','BGCOLOR="#ffffff" TEXT="#ffffe8" LINK="#ccffff" VLINK="#33ccff"

BACKGROUND="/images/back10.jpg"');

htp.header(1,'STATS Database Audit History');

--

htp.tableOpen('Border','','','','WIDTH="100%"');

--

htp.tableRowOpen;

Page 30: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 30

htp.tableHeader('Database');

htp.tableHeader('User Name');

htp.tableHeader('Object Name');

htp.tableHeader('Action');

htp.tableHeader('Return Code');

htp.tableHeader('Day');

htp.tableHeader('Month');

htp.tableHeader('Year');

htp.tableRowClose;

--

htp.tableRowOpen;

htp.tableData(db_nm);

htp.tableData(user_nm);

htp.tableData(object_nm);

htp.tableData(action_nm);

htp.tableData(code);

htp.tableData(day);

htp.tableData(month);

htp.tableData(year);

htp.tableRowClose;

htp.tableClose;

htp.hr;

--

auditrpt (rptcode, db_name, user_name, object_name, action_name, rtcode, webday, webmnth,

webyear);

--

htp.hr;

htp.print('<P><FONT SIZE=2><CITE>');

htp.anchor('/','<IMG BORDER=0 SRC="/images/home-b.jpg">');

htp.anchor('/webstats/owa/webstats.query','<IMG BORDER=0 SRC="/images/up-b.jpg">');

htp.anchor('mailto:[email protected]','<IMG BORDER=0 SRC="/images/mail-b.jpg">');

htp.para;

htp.img('/images/tag1.gif','bottom','Generated by Oracle WebServer');

--

htp.bodyClose;

htp.htmlClose;

end report;

--

-- Procedure auditrpt generates the Server Audit History Report

--

procedure auditrpt (rptcode in varchar2, db_name in varchar2, user_name in varchar2,

Page 31: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 31

object_name in varchar2, action_name in varchar2, rt_code in varchar2,

webday in varchar2, webmonth in varchar2, webyear in varchar2) is

begin

dataheader(rptcode);

getdata (rptcode, db_name, user_name, object_name, action_name, rt_code, webday, webmonth,

webyear);

datafooter;

htp.para;

end auditrpt;

--

-- Procedure dataheader creates the table header for report data

--

procedure dataheader (rptcode in varchar2) is

begin

htp.tableOpen('BORDER','','','','WIDTH="100%"');

--

if rptcode = 'session' then

htp.tableCaption('<B>User Session History</B>');

htp.tableRowOpen;

htp.tableHeader('Database',cattributes=>'valign="bottom" width=');

htp.tableHeader('Timestamp',cattributes=>'valign="bottom" width=');

htp.tableHeader('SID',cattributes=>'valign="bottom" width=');

htp.tableHeader('User Name',cattributes=>'valign="bottom" width=');

htp.tableHeader('OS User Name',cattributes=>'valign="bottom" width=');

htp.tableHeader('Action Name',cattributes=>'valign="bottom" width=');

htp.tableHeader('Return Code',cattributes=>'valign="bottom" width=');

htp.tableHeader('IP Address',cattributes=>'valign="bottom" width=');

htp.tableRowClose;

--

else

htp.tableCaption('<B>Object/Statement History</B>');

htp.tableRowOpen;

htp.tableHeader('Database',cattributes=>'valign="bottom" width=');

htp.tableHeader('Timestamp',cattributes=>'valign="bottom" width=');

htp.tableHeader('SID',cattributes=>'valign="bottom" width=');

htp.tableHeader('User Name',cattributes=>'valign="bottom" width=');

htp.tableHeader('Action Name',cattributes=>'valign="bottom" width=');

htp.tableHeader('Object Owner',cattributes=>'valign="bottom" width=');

htp.tableHeader('Object Name',cattributes=>'valign="bottom" width=');

htp.tableHeader('Return Code',cattributes=>'valign="bottom" width=');

htp.tableRowClose;

Page 32: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 32

end if;

--

end dataheader;

--

-- Procedure datafooter creates the table footer for report data

--

procedure datafooter is

begin

htp.tableClose;

end datafooter;

--

-- Procedure getdata generates the data tables for the reports

--

procedure getdata (rptcode in varchar2, db_name in varchar2, user_name in varchar2,

object_name in varchar2, action_name in varchar2, rtcode in varchar2,

webday in varchar2, webmonth in varchar2, webyear in varchar2) is

querystr varchar2(2000);

begin

if rptcode = 'session' then

querystr := 'select db_id, to_char(timestamp,''DD-MON-YY HH24:MI:SS''),

sessionid, username,

os_username, action_name, returncode, ip_address

from eagle.audit_client_session

where

db_id like :db_nm and

username like :user_nm and

returncode like :code and

to_char(timestamp,''DD'') like :webday and

to_char(timestamp,''Month'') like :webmnth and

to_char(timestamp,''YYYY'') like :webyear

order by timestamp';

--

owa_sql.cells_from_query(

owa_sql.init(querystr,

':db_nm',db_name,

':user_nm',user_name,

':code',rtcode,

':webday',webday,

':webmnth',webmonth,

':webyear',webyear),

Page 33: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 33

10000,'Yes');

else

querystr := 'select db_id, to_char(timestamp,''DD-MON-YY HH24:MI:SS''),

sessionid, username,

action_name, owner, object_name, returncode

from eagle.audit_trail_view

where action like :action_nm and

db_id like :db_nm and

username like :user_nm and

object_name like :object_nm and

returncode like :code and

to_char(timestamp,''DD'') like :webday and

to_char(timestamp,''Month'') like :webmnth and

to_char(timestamp,''YYYY'') like :webyear

order by timestamp';

--

owa_sql.cells_from_query(

owa_sql.init(querystr,

':action_nm',action_name,

':db_nm',db_name,

':user_nm',user_name,

':object_nm',object_name,

':code',rtcode,

':webday',webday,

':webmnth',webmonth,

':webyear',webyear),

10000,'Yes');

end if;

end getdata;

end ;

Audit Trail Configuration

Identify the tablespace in which the audit trail table is located.

select table_name, tablespace_name from dba_tables

where table_name='AUD$' and owner like 'SYS%';

The following instructions are excerpts from Conference Paper 139: Enhancing Database Security: Monitoring

Audit Trails Using Enterprise M anager.

Page 34: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 34

Special Note

Changing either the location or the ownership of AUD$ is a configuration change that is not supported by Oracle

Technical Support. Take care when performing the following steps to ensure the procedures are followed exactly.

While the authors have tested these scripts on a variety of Oracle versions and OS platforms, no warranty,

expressed or implicit, is given that you will have the same results.

Step 1

If auditing is already enabled in the database, it will need to temporarily be disabled while these changes are

made. In the init.ora file, make sure that the audit trail parameter is turned off. Make sure that the value of this

parameter is set to “none”. If the value of this parameter is changed, the database will need to be restarted for the

change to take effect.

Step 2

Check to see if there is already an auditing tablespace in the database. Connect internal using Server Manager and

run the following command.

select tablespace_name from dba_tablespaces;

TABLESPACE_NAME

---------------

SYSTEM

USER_DATA

ROLLBACK_DATA

TEMPORARY_DATA

Step 3

If an auditing tablespace does not exist, execute the following commands as SYS (or internal). Substitute a file

name appropriate to the local operating system, and enter storage parameters consistent with the rest of the

database.

create tablespace "DBAUDIT"

datafile '<use appropriate file name>' size 1m

default storage (initial 128k next 128k pctincrease 0);

Repeat the query from Step 2 to verify that the auditing tablespace has been correctly created.

Step 4

Create the new audit trail table by executing the following commands as SYS (or internal). Substitute storage

parameters consistent with the rest of the database.

rename aud$ to aud$_temp;

create table system.aud$ tablespace "DBAUDIT" storage (initial 64k next 64k pctincrease 0)

as select * from aud$_temp;

Step 5

Connect as SYSTEM and execute the following commands to index and set permissions on the new audit trail

(again substituting appropriate storage parameters):

create index i_aud1 on aud$(sessionid,ses$tid)

tablespace "DBAUDIT" storage (initial 64k next 64k pctincrease 0);

Page 35: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 35

grant all on aud$ to sys with grant option;

Step 6

Connect internal from Server Manager and run these commands to reset and rebuild the auditing portions of

Oracle’s data dictionary:

create view aud$ as select * from system.aud$;

@$ORACLE_HOME/rdbms/admin/cataudit.sql

(if you are using Oracle for Windows95 or WindowsNT, then run

%ORACLE_HOM E%\rdbms73\admin\cataudit.sql or %ORACLE_HOM E%\rdbms80\admin\cataudit.sql)

WatchDog Installation

The following instructions are excerpts from Conference Paper 139: Enhancing Database Security: Monitoring

Audit Trails Using Enterprise M anager.

Step 7

SYSTEM now owns the audit trail. Stop the database and set the following initialization parameters, then restart:

audit_trail = db

utl_file_dir = /your/alert/log/directory/path

where the directory in utl_file_dir is the directory which contains the database alert log; this will allow the audit

trail trigger to update the alert log when an audited event is detected. Any previously existing audits should be

unaffected; all new entries will be written to the new table owned by SYSTEM. The WatchDog trigger can now

be written against AUD$ to automate responses to various events that may show up, like failed logins or other

unusual activities.

Step 8

Make sure any audits that need to be monitored are in place. The following examples will use the session audit to

determine when a login to the database has failed. The session audit is enabled by a DBA with the following

command, issued from Server Manager.

AUDIT SESSION;

Securing the UTL_FILE Package

Before the WatchDog trigger is created, there are some additional security enhancements that can be made to the

database. The UTL_FILE package available in Oracle 7.3 and higher allows stored procedures to have access to

operating system files and directories on the server machine. This package will allow the W atchDog audit trail

trigger to access the database alert log.

UTL_FILE access to operating system directories is controlled by the UTL_FILE_DIR parameter in the init.ora

file for the database. Only files in designated directories can be accessed by UTL_FILE. By default, execute on

UTL_FILE is granted to public, which means that any user in the database has potential read-write access as the

Oracle software owner to the UTL_FILE directories (including the alert log, when the WatchDog configuration

changes in Step 7 are made). This is true even if the user has no other privileges or no user account on the server

operating system. Execute on UTL_FILE should only be granted on an individual basis to trusted and approved

users (preferably only DBAs or trusted software administrators).

Page 36: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 36

Step 9

This security risk is eliminated by revoking the execute grant from public with the following command, executed

as SYS from Server Manager:

REVOKE EXECUTE ON UTL_FILE FROM PUBLIC;

Step 10

Next, regrant the privilege explicitly to SYSTEM.

GRANT EXECUTE ON UTL_FILE TO SYSTEM;

Expanding the Audit Trail Views

Some additional WatchDog views will enhance the quality of information available to the database administrator.

These views make use of information stored in the AUD$ table, but not broken out in the default DBA_AUDIT

views.

WD_AUDIT_CLIENT_SESSION adds two extra columns to the standard DBA_AUDIT_SESSION view:

COMM ENT_TEXT, which contains information about the client connection passed on from the SQL*Net

listener, and IP_ADDRESS, which is stripped from COM MENT_TEXT for TCP protocol connections.

WD_AUDIT_FAILED_SESSION is a subset of W D_AUDIT_CLIENT_SESSION that displays information only

on failed access attempts. This information is very useful when tracking the source of invalid access attempts.

Special Note

If you are using a connection protocol other than TCP, you may need to modify the WatchDog views below to

successfully extract the network address of the database client.

Step 11

To create these views, connect internal to the database using Server Manager, then run the following scripts:

create or replace view wd_audit_client_session as

select os_username, username, userhost, terminal, timestamp, action_name, logoff_time, logoff_lread,

logoff_pread, logoff_lwrite, logoff_dlock, sessionid, returncode, comment_text, session_label,

substr(substr(comment_text,instr(comment_text,'HOST=',1)+5,instr(comment_text,')',

instr(comment_text,'HOST=',1)) - (instr(comment_text,'HOST=',1)+5)),1,15) ip_address

from dba_audit_trail

where action between 100 and 102;

create or replace view wd_audit_failed_session as

select os_username, username, userhost, terminal, timestamp, action_name,

sessionid, returncode, comment_text,

substr(substr(comment_text,instr(comment_text,'HOST=',1)+5,instr(comment_text,')',

instr(comment_text,'HOST=',1)) - (instr(comment_text,'HOST=',1)+5)),1,15) ip_address

from dba_audit_trail

where returncode in (1017,1005,28000) and action between 100 and 102;

create public synonym wd_audit_client_session for sys.wd_audit_client_session;

Page 37: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 37

create public synonym wd_audit_failed_session for sys.wd_audit_failed_session;

grant select on wd_audit_client_session to dba;

grant select on wd_audit_failed_session to dba;

Creating the Trigger

Sample versions of the WatchDog trigger are shown below. These WatchDog triggers report access violations

that return codes 1017 or 1005 during a login attempt (invalid userid/password, or null password). To use these

WatchDogs, insert an appropriate alert file name and directory path where indicated. WatchDog triggers can be

easily modified to record other audited events as well.

Step 12

As SYS, modify and run the appropriate version of the trigger script to create the WatchDog trigger on

system.aud$. Replace the <name of log file> and <path to log file> markers with appropriate values like

‘alertSID.ora’ and ‘/your/alert/log/directory/path’.

Oracle7 Version of WatchDog

CREATE OR REPLACE TRIGGER WATCHDOG

AFTER INSERT ON SYSTEM.AUD$

FOR EACH ROW

DECLARE

FILE_HANDLE UTL_FILE.FILE_TYPE;

ALERT_FILE VARCHAR2(20);

ALERT_PATH VARCHAR2(50);

CURRENT_DATE VARCHAR2(30);

IP_ADDRESS VARCHAR2(15);

PROTOCOL VARCHAR2(10);

BEGIN

/* Check if latest connection is invalid

Code 1005 = Null password, 1017 = Invalid userid/password

Event 100 = LOGON, 101 = LOGOFF, 102 = LOGOFF BY CLEANUP */

IF (:NEW.RETURNCODE IN (1005, 1017)) AND (:NEW.ACTION IN (100,101,102)) THEN

/* Initialize path and file names */

ALERT_FILE := '<name of log file>';

ALERT_PATH := '<path to log file>';

/* Format timestamp for alert log */

CURRENT_DATE := TO_CHAR(:NEW.TIMESTAMP,'Dy Mon DD HH24:MI:SS YYYY');

/* Determine IP Address of client */

IP_ADDRESS := SUBSTR(SUBSTR(:NEW.COMMENT$TEXT,INSTR(:NEW.COMMENT$TEXT,'HOST=',1)+5,

INSTR(:NEW.COMMENT$TEXT,')',INSTR(:NEW.COMMENT$TEXT,'HOST=',1)) –

(INSTR(:NEW.COMMENT$TEXT,'HOST=',1)+5)),1,15);

/* Determine connection protocol of client */

Page 38: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 38

PROTOCOL := NVL(SUBSTR(SUBSTR(:NEW.COMMENT$TEXT,INSTR(:NEW.COMMENT$TEXT, 'PROTOCOL=',1)+9,

INSTR(:NEW.COMMENT$TEXT,')',INSTR(:NEW.COMMENT$TEXT,'PROTOCOL=',1)) -

(INSTR(:NEW.COMMENT$TEXT,'PROTOCOL=',1)+9)),1,10),'ipc');

/* Open alert log for append */

FILE_HANDLE := UTL_FILE.FOPEN(ALERT_PATH,ALERT_FILE,'A');

/* Write alert log entry with [DB User][Terminal][OS User][Protocol][IP Address] */

UTL_FILE.PUT_LINE(FILE_HANDLE,CURRENT_DATE);

UTL_FILE.PUT_LINE(FILE_HANDLE,'ORA-0'||:NEW.RETURNCODE||': Logon denied ['||:NEW.USERID||

'] ['||:NEW.TERMINAL||'] ['||:NEW.SPARE1||'] ['||PROTOCOL||'] ['||IP_ADDRESS||']');

/* Close alert log */

UTL_FILE.FCLOSE (FILE_HANDLE);

END IF;

EXCEPTION

WHEN NO_DATA_FOUND THEN UTL_FILE.FCLOSE(FILE_HANDLE);

WHEN UTL_FILE.INVALID_PATH THEN UTL_FILE.FCLOSE(FILE_HANDLE);

WHEN UTL_FILE.READ_ERROR THEN UTL_FILE.FCLOSE(FILE_HANDLE);

WHEN UTL_FILE.WRITE_ERROR THEN UTL_FILE.FCLOSE(FILE_HANDLE);

WHEN OTHERS THEN UTL_FILE.FCLOSE(FILE_HANDLE);

END;

Oracle8 Version of WatchDog

CREATE OR REPLACE TRIGGER WATCHDOG

AFTER INSERT ON SYSTEM.AUD$

FOR EACH ROW

DECLARE

FILE_HANDLE UTL_FILE.FILE_TYPE;

ALERT_FILE VARCHAR2(20);

ALERT_PATH VARCHAR2(50);

CURRENT_DATE VARCHAR2(30);

IP_ADDRESS VARCHAR2(15);

PROTOCOL VARCHAR2(10);

BEGIN

/* Check if connection attempt is invalid

Code 1005 = Null password, 1017 = Invalid userid/password, 28000 = Account locked (v8 only)

Event 100 = LOGON, 101 = LOGOFF, 102 = LOGOFF BY CLEANUP */

IF (:NEW.RETURNCODE IN (1005, 1017, 28000)) AND (:NEW.ACTION# IN (100,101,102)) THEN

/* Initialize path and file names */

ALERT_FILE := '<name of log file>';

ALERT_PATH := '<path to log file>';

/* Format timestamp for alert log */

Page 39: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 39

CURRENT_DATE := TO_CHAR(:NEW.TIMESTAMP#,'Dy Mon DD HH24:MI:SS YYYY');

/* Determine IP Address of client, if available */

IP_ADDRESS := SUBSTR(SUBSTR(:NEW.COMMENT$TEXT,INSTR(:NEW.COMMENT$TEXT,'HOST=',1)+5,

INSTR(:NEW.COMMENT$TEXT,')',INSTR(:NEW.COMMENT$TEXT,'HOST=',1)) -

(INSTR(:NEW.COMMENT$TEXT,'HOST=',1)+5)),1,15);

/* Determine connection protocol of client */

PROTOCOL := NVL(SUBSTR(SUBSTR(:NEW.COMMENT$TEXT,INSTR(:NEW.COMMENT$TEXT,'PROTOCOL=',1)+9,

INSTR(:NEW.COMMENT$TEXT,')',INSTR(:NEW.COMMENT$TEXT,'PROTOCOL=',1)) -

(INSTR(:NEW.COMMENT$TEXT,'PROTOCOL=',1)+9)),1,10),'ipc');

/* Open alert log for append */

FILE_HANDLE := UTL_FILE.FOPEN(ALERT_PATH,ALERT_FILE,'A');

/* Write alert log entry with [DB User][Terminal][OS User][Protocol][IP Address] */

UTL_FILE.PUT_LINE (FILE_HANDLE,CURRENT_DATE);

UTL_FILE.PUT_LINE (FILE_HANDLE,'ORA-0'||:NEW.RETURNCODE||': Logon denied ['||:NEW.USERID||

'] ['||:NEW.TERMINAL||'] ['||:NEW.SPARE1||'] ['||PROTOCOL||'] ['||IP_ADDRESS||']');

/* Close alert log */

UTL_FILE.FCLOSE (FILE_HANDLE);

END IF;

EXCEPTION

WHEN NO_DATA_FOUND THEN UTL_FILE.FCLOSE(FILE_HANDLE);

WHEN UTL_FILE.INVALID_PATH THEN UTL_FILE.FCLOSE(FILE_HANDLE);

WHEN UTL_FILE.READ_ERROR THEN UTL_FILE.FCLOSE(FILE_HANDLE);

WHEN UTL_FILE.WRITE_ERROR THEN UTL_FILE.FCLOSE(FILE_HANDLE);

WHEN OTHERS THEN UTL_FILE.FCLOSE(FILE_HANDLE);

END;

Special Note

Be sure to create the WatchDog trigger as SYS. Otherwise you may encounter an ORA-03113 (“end-of-file on

communication channel”) error on the client (i.e. SQL*Plus), and generate an ORA-07445 (“exception

encountered: core dump [%s]”) error or ORA-00600 (“internal message code, arguments: [num]”) error on the

server when you try to log in.

OEM Configuration

The following instructions are excerpts from Conference Paper 139: Enhancing Database Security: Monitoring

Audit Trails Using Enterprise M anager.

Step 13

It is assumed that the Oracle Enterprise Manager (OEM) and Diagnostics Pack have been installed, and that the

OEM console is running. It is also assumed that the DBSNMP services for each monitored database have been

correctly configured and started on each host platform (see the Oracle Enterprise Manager Installation Guide,

Chapters 1 and 2 for complete instructions). Select the Event Set Library tab in the Event pane. From the Event

menu, select Create Event Set.

Page 40: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 40

Step 14

In the General tab of the Create Event Set dialog box, enter the name of the new event set, “W atchDog Security”.

Make sure that the Service Type field is set to “Database”. Enter a description of the event set, “Custom Database

Security Event Set”. In the Events tab of the Create Event Set dialog box, double click on the “Alert” event in the

Available Events list. It should move to the Selected Events list. In the Parameters tab of the Create Event Set

dialog box, set the frequency with which the alert log should be checked for new messages. A time of several

minutes is generally sufficient. When the frequency has been correctly set, click the OK button at the bottom of

the dialog box.

Step 15

Select the new event set from the list of event sets in the Event Set Library. Select Register Event Set from the

Event menu. In the Register Event Set dialog box, select the databases to be registered from the Available

Destinations. Each database should appear in the Selected Destinations list as it is selected. When the desired

databases have been selected, click the OK button at the bottom of the dialog box.

Each selected database should now be registered to report any “ORA” error messages that appear in the alert log

directly to the OEM console.

Modifications to Eagle

GuardDog DDL:

/*

Script 1: GuardDog DDL

This script creates the objects required to support GuardDog.

Note: If you are installing GuardDog into an existing Eagle system

you may skip all of the DDL commands between this comment the

one below

*/

CREATE TABLE DATABASE (

DB_ID VARCHAR2(12) NOT NULL,

DB_NAME VARCHAR2(30) NOT NULL,

DB_LINK VARCHAR2(30) NOT NULL

)

PCTFREE 5

PCTUSED 95

INITRANS 1

MAXTRANS 255

TABLESPACE USERS

STORAGE (

INITIAL 16K

NEXT 16K

MINEXTENTS 1

Page 41: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 41

MAXEXTENTS 121

PCTINCREASE 0

)

;

ALTER TABLE DATABASE

ADD ( PRIMARY KEY (DB_ID)

USING INDEX

PCTFREE 5

INITRANS 2

MAXTRANS 255

TABLESPACE USER_IDX

STORAGE (

INITIAL 16K

NEXT 16K

MINEXTENTS 1

MAXEXTENTS 121

PCTINCREASE 0

) ) ;

/*

The previous DDL commands can be skipped when installing Guard Dog

into an existing Eagle schema. All DDL from this point on must be

run when installing Guard Dog in any schema.

*/

CREATE TABLE MONITOR (

MONITOR_ID VARCHAR2(12) NOT NULL,

NAME VARCHAR2(50) NULL,

PREPARE1_CLAUSE VARCHAR2(256) NULL,

PREPARE2_CLAUSE VARCHAR2(256) NULL,

INSERT_CLAUSE VARCHAR2(256) NULL,

SELECT_CLAUSE VARCHAR2(256) NULL,

WHERE_CLAUSE VARCHAR2(256) NULL,

CLOSE1_CLAUSE VARCHAR2(500) NULL,

CLOSE2_CLAUSE VARCHAR2(256) NULL,

COMMENT_TEXT VARCHAR2(2000) NULL

);

ALTER TABLE MONITOR

ADD ( PRIMARY KEY (MONITOR_ID)

Page 42: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 42

USING INDEX

PCTFREE 1

INITRANS 2

MAXTRANS 255

TABLESPACE USER_IDX

STORAGE (

INITIAL 50k

NEXT 50k

MINEXTENTS 1

MAXEXTENTS 121

PCTINCREASE 0

FREELISTS 2

) ) ;

CREATE TABLE DB_MONITOR (

DB_ID VARCHAR2(12) NOT NULL,

MONITOR_ID VARCHAR2(12) NOT NULL,

ACTIVE_YN VARCHAR2(1) NULL

)

PCTFREE 5

PCTUSED 95

INITRANS 1

MAXTRANS 255

TABLESPACE USERS

STORAGE (

INITIAL 50k

NEXT 50k

MINEXTENTS 1

MAXEXTENTS 121

PCTINCREASE 0

) ;

CREATE INDEX XIF19DB_MONITOR ON DB_MONITOR

(

DB_ID

)

PCTFREE 1

INITRANS 2

MAXTRANS 255

TABLESPACE USER_IDX

STORAGE (

INITIAL 50k

Page 43: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 43

NEXT 50k

MINEXTENTS 1

MAXEXTENTS 121

PCTINCREASE 0

FREELISTS 2

) ;

CREATE INDEX XIF20DB_MONITOR ON DB_MONITOR

(

MONITOR_ID

)

PCTFREE 1

INITRANS 2

MAXTRANS 255

TABLESPACE USER_IDX

STORAGE (

INITIAL 50k

NEXT 50k

MINEXTENTS 1

MAXEXTENTS 121

PCTINCREASE 0

FREELISTS 2

) ;

ALTER TABLE DB_MONITOR

ADD ( PRIMARY KEY (DB_ID, MONITOR_ID) ) ;

CREATE TABLE DB_MONITOR_CRITERIA (

DB_ID VARCHAR2(12) NULL,

MONITOR_ID VARCHAR2(12) NULL,

CRITERIA_TYPE VARCHAR2(10) NULL,

PARAMETER VARCHAR2(256) NULL,

VALUE1 VARCHAR2(256) NULL,

VALUE2 VARCHAR2(256) NULL,

SCORE NUMBER NULL,

COMMENT_TEXT VARCHAR2(2000) NULL

)

PCTFREE 5

PCTUSED 95

INITRANS 1

MAXTRANS 255

TABLESPACE USERS

STORAGE (

Page 44: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 44

INITIAL 128k

NEXT 128k

MINEXTENTS 1

MAXEXTENTS 121

PCTINCREASE 0

) ;

CREATE INDEX XIF22DB_MONITOR_EXCEPTION ON DB_MONITOR_CRITERIA

(

DB_ID,

MONITOR_ID

)

PCTFREE 1

INITRANS 2

MAXTRANS 255

TABLESPACE USER_IDX

STORAGE (

INITIAL 128k

NEXT 128k

MINEXTENTS 1

MAXEXTENTS 121

PCTINCREASE 0

FREELISTS 2

) ;

CREATE TABLE DB_MONITOR_REPORT (

DB_ID VARCHAR2(12) NULL,

MONITOR_ID VARCHAR2(12) NULL,

RUN_TIME DATE NULL,

PARAMETER VARCHAR2(256) NULL,

VALUE1 VARCHAR2(256) NULL,

VALUE2 VARCHAR2(256) NULL,

SCORE NUMBER NULL,

COMMENT_TEXT VARCHAR2(2000) NULL

)

PCTFREE 5

PCTUSED 95

INITRANS 1

MAXTRANS 255

TABLESPACE USERS

STORAGE (

INITIAL 128k

Page 45: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 45

NEXT 128k

MINEXTENTS 1

MAXEXTENTS 121

PCTINCREASE 0

) ;

CREATE INDEX XIF23DB_MONITOR_REPORT ON DB_MONITOR_REPORT

(

DB_ID,

MONITOR_ID

)

PCTFREE 1

INITRANS 2

MAXTRANS 255

TABLESPACE USER_IDX

STORAGE (

INITIAL 128k

NEXT 128k

MINEXTENTS 1

MAXEXTENTS 121

PCTINCREASE 0

FREELISTS 2

) ;

CREATE TABLE DB_MONITOR_RESULT (

DB_ID VARCHAR2(12) NULL,

MONITOR_ID VARCHAR2(12) NULL,

RUN_TIME DATE NULL,

PARAMETER VARCHAR2(256) NULL,

VALUE1 VARCHAR2(256) NULL,

VALUE2 VARCHAR2(256) NULL

)

PCTFREE 5

PCTUSED 95

INITRANS 1

MAXTRANS 255

TABLESPACE USERS

STORAGE (

INITIAL 512k

NEXT 128k

MINEXTENTS 1

MAXEXTENTS 121

Page 46: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 46

PCTINCREASE 0

) ;

CREATE INDEX XIF21DB_MONITOR_RESULT ON DB_MONITOR_RESULT

(

DB_ID,

MONITOR_ID

)

PCTFREE 1

INITRANS 2

MAXTRANS 255

TABLESPACE USER_IDX

STORAGE (

INITIAL 128k

NEXT 128k

MINEXTENTS 1

MAXEXTENTS 121

PCTINCREASE 0

FREELISTS 2

) ;

ALTER TABLE DB_MONITOR

ADD ( FOREIGN KEY (MONITOR_ID)

REFERENCES MONITOR ) ;

ALTER TABLE DB_MONITOR

ADD ( FOREIGN KEY (DB_ID)

REFERENCES DATABASE ) ;

ALTER TABLE DB_MONITOR_REPORT

ADD ( FOREIGN KEY (DB_ID, MONITOR_ID)

REFERENCES DB_MONITOR ) ;

ALTER TABLE DB_MONITOR_RESULT

ADD ( FOREIGN KEY (DB_ID, MONITOR_ID)

REFERENCES DB_MONITOR ) ;

GuardDog PL/SQL

GuardDog PL/SQL Package:

/*

Script 2: GuardDog PL/SQL Package

This script creates the GUARD_DOG package which is the core of the GuardDog

system. This package requires that all of the GuardDog objects have already

been created using Script 1. This script should be run in the GuardDog schema.

Page 47: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 47

The GUARD_DOG package is composed of two procedures. FETCH_DATA selects all

information for the evaluation from the target database. PARSE_DATA compares

the selected data against the predefined evaluation criteria.

*/

CREATE OR REPLACE PACKAGE GUARD_DOG AS

procedure fetch_data (DBID in VARCHAR2);

procedure parse_data (DBID in VARCHAR2);

END GUARD_DOG;

CREATE OR REPLACE PACKAGE BODY GUARD_DOG AS

/*

Procedure FETCH_DATA gathers the audit evaluation data from the designated

Oracle instance. Active monitor information is read from the monitor table

and raw data is inserted into the db_monitor_results table. All previous

raw data for the current database/monitor is generally deleted before new

data is inserted.

*/

PROCEDURE FETCH_DATA (DBID in VARCHAR2) AS

no_connection EXCEPTION;

PRAGMA EXCEPTION_INIT(no_connection, -12203);

CURSOR C_DB_MONITOR (DB VARCHAR2) IS

SELECT DB_ID, MONITOR_ID, ACTIVE_YN

FROM DB_MONITOR WHERE DB_ID LIKE DB ORDER BY DB_ID;

db_monitor_rec DB_MONITOR%ROWTYPE ;

monitor_rec MONITOR%ROWTYPE ;

database_rec DATABASE%ROWTYPE ;

sql_stmt VARCHAR2(1000) ;

ret_val INTEGER ;

cursor_id INTEGER ;

c_get_data INTEGER ;

temp_clause VARCHAR2(256) ;

BEGIN

/* Open list of monitors for processing */

OPEN C_DB_MONITOR(DBID);

LOOP

Page 48: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 48

FETCH C_DB_MONITOR INTO db_monitor_rec;

EXIT WHEN C_DB_MONITOR%NOTFOUND ;

/* If the current monitor is active, then process */

IF db_monitor_rec.active_yn = 'Y' THEN

/* Get monitor record */

select * into monitor_rec from monitor

where monitor_id = db_monitor_rec.monitor_id ;

/* Get database record */

select * into database_rec from database

where db_id = db_monitor_rec.db_id ;

/* Substiture database and link names into monitor queries */

monitor_rec.select_clause := REPLACE(monitor_rec.select_clause,

'<DB_ID>',database_rec.db_id);

monitor_rec.select_clause := REPLACE(monitor_rec.select_clause,

'<DB_LINK>',database_rec.db_link);

monitor_rec.where_clause := REPLACE(monitor_rec.where_clause,

'<DB_ID>',database_rec.db_id);

/* Construct final insert / select statement */

sql_stmt := monitor_rec.insert_clause ||

monitor_rec.select_clause ||

monitor_rec.where_clause;

/* Process first prepare clause */

if monitor_rec.prepare1_clause is not null then

/* Substitute database and link names into first prepare statement */

monitor_rec.prepare1_clause := REPLACE(monitor_rec.prepare1_clause,

'<DB_ID>',database_rec.db_id);

monitor_rec.prepare1_clause := REPLACE(monitor_rec.prepare1_clause,

'<DB_LINK>',database_rec.db_link);

/* Execute first prepare clause */

cursor_id := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_id,monitor_rec.prepare1_clause,DBMS_SQL.V7);

ret_val := DBMS_SQL.EXECUTE(cursor_id) ;

Page 49: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 49

DBMS_SQL.CLOSE_CURSOR(cursor_id);

end if;

/* Process second prepare clause */

if monitor_rec.prepare2_clause is not null then

/* Substitute database and link names into second prepare statement */

monitor_rec.prepare2_clause := REPLACE(monitor_rec.prepare2_clause,

'<DB_ID>',database_rec.db_id);

monitor_rec.prepare2_clause := REPLACE(monitor_rec.prepare2_clause,

'<DB_LINK>',database_rec.db_link);

/* Execute second prepare clause */

cursor_id := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_id,monitor_rec.prepare2_clause,DBMS_SQL.V7);

ret_val := DBMS_SQL.EXECUTE(cursor_id) ;

DBMS_SQL.CLOSE_CURSOR(cursor_id);

end if;

/* Execute monitor insert / select statement */

c_get_data := DBMS_SQL.OPEN_CURSOR ;

DBMS_SQL.PARSE(c_get_data,sql_stmt,DBMS_SQL.V7) ;

ret_val := DBMS_SQL.EXECUTE(c_get_data) ;

DBMS_SQL.CLOSE_CURSOR(c_get_data) ;

/* Process first close clause */

if monitor_rec.close1_clause is not null then

/* Substitute database and link names into first close clause */

monitor_rec.close1_clause := REPLACE(monitor_rec.close1_clause,

'<DB_ID>',database_rec.db_id);

monitor_rec.close1_clause := REPLACE(monitor_rec.close1_clause,

'<DB_LINK>',database_rec.db_link);

/* Execute first close clause */

cursor_id := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_id,monitor_rec.close1_clause,DBMS_SQL.V7);

ret_val := DBMS_SQL.EXECUTE(cursor_id) ;

DBMS_SQL.CLOSE_CURSOR(cursor_id);

end if;

Page 50: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 50

/* Process second close clause */

if monitor_rec.close2_clause is not null then

/* Substitute database and link names into second close clause */

monitor_rec.close2_clause := REPLACE(monitor_rec.close2_clause,

'<DB_ID>',database_rec.db_id);

monitor_rec.close2_clause := REPLACE(monitor_rec.close2_clause,

'<DB_LINK>',database_rec.db_link);

/* Execute second close clause */

cursor_id := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_id,monitor_rec.close2_clause,DBMS_SQL.V7);

ret_val := DBMS_SQL.EXECUTE(cursor_id) ;

DBMS_SQL.CLOSE_CURSOR(cursor_id);

end if;

commit;

end if;

end loop;

END FETCH_DATA;

/*

Procedure PARSE_DATA compares the data gathered by FETCH_DATA with the

criteria designated in the db_monitor_criteria table for the given monitor

and/or database. First, each piece of raw data is compared to the required,

forbidden, or suppressed criteria to look for violations. Second, all

required criteria are compared to the raw data to determine if any are missing.

Results of the comparison are inserted into the db_monitor_report table.

Any previous report for the designated database is deleted before the

comparison begins.

*/

PROCEDURE PARSE_DATA (DBID in VARCHAR2) AS

cursor C_DB_MONITOR_RESULT (DB VARCHAR2) is

select r.* from db_monitor_result r, db_monitor m

where r.db_id like DB and r.db_id = m.db_id and r.monitor_id = m.monitor_id and

m.active_yn='Y' order by r.db_id, r.monitor_id;

cursor C_DB_MONITOR_CRITERIA (MON_ID VARCHAR2, PRM_ID VARCHAR2) is

select * from db_monitor_criteria

where db_id='DEFAULT' and

Page 51: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 51

monitor_id=MON_ID and

parameter in (PRM_ID,'%');

cursor C_DB_MONITOR_SUPRESS (DBID VARCHAR2, MON_ID VARCHAR2, PRM_ID VARCHAR2,

VAL1 VARCHAR2, VAL2 VARCHAR2) is

select * from db_monitor_criteria

where db_id = DBID and

monitor_id = MON_ID and

criteria_type = 'SUPPRESSED' and

parameter like PRM_ID and

nvl(value1,'null') like nvl(VAL1,'null') and

nvl(value2,'null') like nvl(VAL2,'null');

cursor C_DB_MONITOR_REQUIRED is

select * from db_monitor_criteria

where db_id='DEFAULT' and

criteria_type='REQUIRED';

cursor C_DB_MONITOR_MISSING (DBID VARCHAR2, MON_ID VARCHAR2, PRM_ID VARCHAR2) is

select * from db_monitor_report

where db_id = DBID and

monitor_id = MON_ID and

parameter like PRM_ID;

db_mon_result_rec DB_MONITOR_RESULT%ROWTYPE ;

criteria_rec DB_MONITOR_CRITERIA%ROWTYPE ;

suppressed_rec DB_MONITOR_CRITERIA%ROWTYPE ;

required_rec DB_MONITOR_CRITERIA%ROWTYPE ;

missing_rec DB_MONITOR_REPORT%ROWTYPE ;

BEGIN

delete from db_monitor_report where db_id like DBID;

commit;

/* open set of raw data gathered from database and compare to basic criteria */

open C_DB_MONITOR_RESULT(DBID);

loop

fetch C_DB_MONITOR_RESULT into db_mon_result_rec;

exit when C_DB_MONITOR_RESULT%NOTFOUND ;

/* Compare current result record against basic criteria */

open C_DB_MONITOR_CRITERIA(db_mon_result_rec.monitor_id,

db_mon_result_rec.parameter);

fetch C_DB_MONITOR_CRITERIA into criteria_rec;

Page 52: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 52

/* If no criteria is found then current record is EXTRA */

if C_DB_MONITOR_CRITERIA%NOTFOUND then

insert into db_monitor_report (db_id, monitor_id, run_time, parameter, value1,

value2, score, comment_text) values (db_mon_result_rec.db_id,

db_mon_result_rec.monitor_id, db_mon_result_rec.run_time,

db_mon_result_rec.parameter, db_mon_result_rec.value1, db_mon_result_rec.value2,

0, 'No evaluation criteria exist for this parameter');

/* If criteria indicates a required value, compare to recorded value */

elsif criteria_rec.criteria_type = 'REQUIRED' then

/* If values match or criteria null then OK */

if (nvl(db_mon_result_rec.value1,'null') like nvl(criteria_rec.value1,'%') and

nvl(db_mon_result_rec.value2,'null') like nvl(criteria_rec.value2,'%')) or

(criteria_rec.value1 is null and criteria_rec.value2 is null) then

insert into db_monitor_report (db_id, monitor_id, run_time, parameter, value1,

value2, score, comment_text) values (db_mon_result_rec.db_id,

db_mon_result_rec.monitor_id, db_mon_result_rec.run_time,

db_mon_result_rec.parameter, db_mon_result_rec.value1,

db_mon_result_rec.value2, 0, 'OK');

/* If values do not match then NOT OK or SUPPRESSED */

else

/* Check list of suppressed values */

open C_DB_MONITOR_SUPRESS(db_mon_result_rec.db_id, db_mon_result_rec.monitor_id,

db_mon_result_rec.parameter, db_mon_result_rec.value1,

db_mon_result_rec.value2);

fetch C_DB_MONITOR_SUPRESS into suppressed_rec;

/* If not on suppressed list then NOT OK */

if C_DB_MONITOR_SUPRESS%NOTFOUND then

insert into db_monitor_report (db_id, monitor_id, run_time, parameter, value1,

value2, score, comment_text) values (db_mon_result_rec.db_id,

db_mon_result_rec.monitor_id, db_mon_result_rec.run_time,

db_mon_result_rec.parameter, db_mon_result_rec.value1,

db_mon_result_rec.value2, criteria_rec.score, criteria_rec.comment_text);

end if;

close C_DB_MONITOR_SUPRESS;

end if;

Page 53: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 53

/* If criteria indicates a forbidden value then compare to recorded value */

elsif criteria_rec.criteria_type = 'FORBIDDEN' then

/* If values match or criteria null then NOT OK or SUPPRESSED */

if (nvl(db_mon_result_rec.value1,'null') like nvl(criteria_rec.value1,'%') and

nvl(db_mon_result_rec.value2,'null') like nvl(criteria_rec.value2,'%')) or

(criteria_rec.value1 is null and criteria_rec.value2 is null) then

/* Check list of suppressed values */

open C_DB_MONITOR_SUPRESS(db_mon_result_rec.db_id, db_mon_result_rec.monitor_id,

db_mon_result_rec.parameter, db_mon_result_rec.value1,

db_mon_result_rec.value2);

fetch C_DB_MONITOR_SUPRESS into suppressed_rec;

/* If not on suppressed list then NOT OK */

if C_DB_MONITOR_SUPRESS%NOTFOUND then

insert into db_monitor_report (db_id, monitor_id, run_time, parameter, value1,

value2, score, comment_text) values (db_mon_result_rec.db_id,

db_mon_result_rec.monitor_id, db_mon_result_rec.run_time,

db_mon_result_rec.parameter, db_mon_result_rec.value1,

db_mon_result_rec.value2, criteria_rec.score, criteria_rec.comment_text);

end if;

close C_DB_MONITOR_SUPRESS;

/* If values do not match then OK */

else

insert into db_monitor_report (db_id, monitor_id, run_time, parameter, value1,

value2, score, comment_text) values (db_mon_result_rec.db_id,

db_mon_result_rec.monitor_id, db_mon_result_rec.run_time,

db_mon_result_rec.parameter, db_mon_result_rec.value1,

db_mon_result_rec.value2, 0, 'OK');

end if;

end if;

close C_DB_MONITOR_CRITERIA;

end loop;

open C_DB_MONITOR_REQUIRED;

loop

fetch C_DB_MONITOR_REQUIRED into required_rec;

Page 54: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 54

exit when C_DB_MONITOR_REQUIRED%NOTFOUND ;

/* Compare current required criteria against result records from database */

open C_DB_MONITOR_MISSING(DBID, required_rec.monitor_id, required_rec.parameter);

fetch C_DB_MONITOR_MISSING into missing_rec;

/* If no matching record is found then criteria is MISSING or SUPPRESSED */

if C_DB_MONITOR_MISSING%NOTFOUND then

open C_DB_MONITOR_SUPRESS(DBID, required_rec.monitor_id, required_rec.parameter,

'%', '%');

fetch C_DB_MONITOR_SUPRESS into suppressed_rec;

/* If not on suppressed list then MISSING */

if C_DB_MONITOR_SUPRESS%NOTFOUND then

insert into db_monitor_report (db_id, monitor_id, run_time, parameter, value1,

value2, score, comment_text) values (DBID, required_rec.monitor_id, sysdate,

required_rec.parameter, required_rec.value1, required_rec.value2,

required_rec.score, required_rec.comment_text);

end if;

close C_DB_MONITOR_SUPRESS;

end if;

close C_DB_MONITOR_MISSING;

end loop;

commit;

END PARSE_DATA;

END GUARD_DOG;

GuardDog Configuration

Standard Monitors:

/*

Script 5: GuardDog Standard Monitors

This script creates the GuardDog standard monitors. A definition for each monitor

is inserted into the MONITOR table. You may wish to modify these monitors to meet

specific requirements of your system. For example, by default each monitor deletes

the data selected in its last run before beginning a new one.

*/

/* The IDLE_TIME monitor selects the idle time for each user */

insert into monitor

Page 55: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 55

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('IDLE_TIME','User Idle Time Limit',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''IDLE_TIME'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1) ',

'select ''<DB_ID>'', ''IDLE_TIME'', sysdate, u.username, p.limit from dba_users@<DB_LINK> u,

dba_profiles@<DB_LINK> p ',

'where u.profile = p.profile and p.resource_name=''IDLE_TIME'' ','commit ','',

'User Idle Time

- Idle time must be set for all database users

- The Oracle "default" profile must be altered or a new profile created');

/* The INIT_PARAM monitor selects all initialization parameters for the instance */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('INIT_PARAM','Initialization Parameters',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''INIT_PARAM'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1, value2) ',

'select ''<DB_ID>'', ''INIT_PARAM'', sysdate, name, value, isdefault from v$parameter@<DB_LINK>

',' ','commit ','',

'Initialization Parameters

- The UTL_FILE_DIR parameter must not be set to "*"

- The audit_trail parameter must be set to "db"

- The resource_limit parameter must be set to "true"

- The remote_os_authent parameter must be set to "false"

- The remote_os_roles parameter must be set to "false"

- The os_roles parameter must be set to "false"

- The dblink_encrypt_login parameter must be set to "true"');

/* The OBJ_PRIVS1 monitor selects Alter and References privileges granted to users other

than SYS and SYSTEM */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

Page 56: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 56

('OBJ_PRIVS1','Object Privileges Granted to Users',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''OBJ_PRIVS1'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1, value2)', 'select

''<DB_ID>'', ''OBJ_PRIVS1'', sysdate, t.grantee, t.owner || ''.'' || t.table_name, t.privilege

from dba_tab_privs@<DB_LINK> t, dba_users@<DB_LINK> u ',

'where (u.username = t.grantee or t.grantee = ''PUBLIC'') and t.privilege in

(''ALTER'',''REFERENCES'') and t.grantee not in (''SYS'',''SYSTEM'') ',

'commit ','',

'Object Privileges

- No application user may be granted "ALTER" object privilege

- No application user may be granted "REFERENCES" object privilege');

/* The OBJ_PRIVS2 monitor selects Alter and References privileges granted to

non-std roles */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('OBJ_PRIVS2','Object Privileges Granted to Roles',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''OBJ_PRIVS2'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1, value2) ',

'select ''<DB_ID>'', ''OBJ_PRIVS2'', sysdate, t.grantee, t.owner || ''.'' || t.table_name,

t.privilege from dba_tab_privs@<DB_LINK> t, dba_roles@<DB_LINK> r ',

'where r.role = t.grantee and t.privilege in (''ALTER'',''REFERENCES'') and r.role not in

(''DBA'',''RESOURCE'',''IMP_FULL_DATABASE'',''EXP_FULL_DATABASE'',''CONNECT'') ',

'commit ','',

'Object Privileges

- No application user may be granted "ALTER" object privilege

- No application user may be granted "REFERENCES" object privilege');

/* The ORACLE_ROLES monitor selects standard Oracle roles that are granted to users

other than SYS, SYSTEM, and DBA */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('ORACLE_ROLES','Oracle Roles Granted to Users and Roles',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''ORACLE_ROLES'' ', '',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1) ',

Page 57: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 57

'select ''<DB_ID>'', ''ORACLE_ROLES'', sysdate, r.grantee, r.granted_role from

dba_role_privs@<DB_LINK> r ',

'where r.granted_role in (''DBA'',''EXP_FULL_DATABASE'',''IMP_FULL_DATABASE'',''OSOPER'',

''OSDBA'') and r.grantee not in (''SYS'',''SYSTEM'',''DBA'') ','commit ','',

'Oracle Predefined Roles

- No application user may be granted DBA, EXP_FULL_DATABASE, IMP_FULL_DATABASE

- These roles must not be granted to PUBLIC');

/* The SYS_ADMIN1 monitor selects users with ADMIN priveleges on system/object

privileges */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('SYS_ADMIN1','Users with ADMIN on System/Object Privileges',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''SYS_ADMIN1'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1, value2) ',

'select ''<DB_ID>'', ''SYS_ADMIN1'', sysdate, p.grantee, p.privilege, p.admin_option from

dba_sys_privs@<DB_LINK> p, dba_users@<DB_LINK> u ',

'where (u.username = p.grantee or p.grantee=''PUBLIC'') and p.admin_option=''YES'' and p.grantee

not in (''SYS'',''SYSTEM'') ','commit ','',

'Oracle Privilege Administration

- No application user may have ADMIN option of any system or object privilege

- No application user may have ADMIN option on any predefined role');

/* The SYS_ADMIN2 monitor selects users with ADMIN privileges on standard roles */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('SYS_ADMIN2','Users with ADMIN on Oracle Predefined Roles',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''SYS_ADMIN2'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1, value2) ',

'select ''<DB_ID>'', ''SYS_ADMIN2'', sysdate, r.grantee, r.granted_role, r.admin_option from

dba_role_privs@<DB_LINK> r, dba_users@<DB_LINK> u ',

'where u.username = r.grantee and r.granted_role in (''DBA'',''RESOURCE'', ''IMP_FULL_DATABASE'',

''EXP_FULL_DATABASE'', ''CONNECT'',''SNMPAGENT'') and r.admin_option=''YES'' and r.grantee not in

(''SYS'',''SYSTEM'') ','commit ','',

'Oracle Privilege Administration

Page 58: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 58

- No application user may have ADMIN option of any system or object privilege

- No application user may have ADMIN option on any predefined role');

/* The SYS_AUDIT2 monitor selects statement level audits that have been enabled */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('SYS_AUDIT2','Audit Statement Options',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''SYS_AUDIT2'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1, value2) ',

'select ''<DB_ID>'', ''SYS_AUDIT2'', sysdate, audit_option, success, failure from

dba_stmt_audit_opts@<DB_LINK> ',' ','commit ','',

'Mandatory Auditing');

/* The SYS_PRIVS1 monitor selects system privileges granted to users other than SYS

and SYSTEM */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('SYS_PRIVS1','System Privileges Granted to Users',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''SYS_PRIVS1'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1) ',

'select ''<DB_ID>'', ''SYS_PRIVS1'', sysdate, p.grantee, p.privilege from dba_sys_privs@<DB_LINK>

p, dba_users@<DB_LINK> u ',

'where (u.username = p.grantee or p.grantee=''PUBLIC'') and p.grantee not in

(''SYS'',''SYSTEM'',''DBSNMP'') ','commit ','',

'System Privileges

- Oracle system privileges must not be granted to PUBLIC

- No "ANY" system privilege may be granted to an application user

- No application user may have ALTER USER privilege

- No application user may be allowed to disable auditing');

/* The SYS_PRIVS2 monitor selects system privileges granted to non-std roles */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

Page 59: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 59

values

('SYS_PRIVS2','System Privileges Granted to Roles',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''SYS_PRIVS2'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1) ',

'select ''<DB_ID>'', ''SYS_PRIVS2'', sysdate, p.grantee, p.privilege from dba_sys_privs@<DB_LINK>

p, dba_roles@<DB_LINK> r ',

'where r.role = p.grantee and r.role not in (''DBA'',''RESOURCE'',''IMP_FULL_DATABASE'',

''EXP_FULL_DATABASE'',''CONNECT'',''SNMPAGENT'') ','commit ','',

'System Privileges

- Oracle system privileges must not be granted to PUBLIC

- No "ANY" system privilege may be granted to an application user

- No application user may have ALTER USER privilege

- No application user may be allowed to disable auditing');

/* The APP_ROLES1 monitor selects all non-standard (application) roles */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('APP_ROLES1','Non-Predefined Roles',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''APP_ROLES1'' ',

'','insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1) ',

'select ''<DB_ID>'', ''APP_ROLES1'', sysdate, r.role, r.password_required from

dba_roles@<DB_LINK> r ',

'where r.role not in (''DBA'', ''RESOURCE'', ''IMP_FULL_DATABASE'',''EXP_FULL_DATABASE'',

''CONNECT'', ''SNMPAGENT'') ','commit ','',

'Application Roles

- Every application must create distinct roles containing all necessary privileges for

application users and administrators

- All roles created and used by an application must be password protected

- All application users must be granted the appropriate application role

- No user may have an application role assigned as the default role');

/* The APP_ROLES2 monitor selects all users assigned to non-standard roles */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

Page 60: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 60

('APP_ROLES2','Users Assigned to Non-Predefined Roles',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''APP_ROLES2'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1, value2) ',

'select ''<DB_ID>'', ''APP_ROLES2'', sysdate, r.grantee, r.granted_role, r.admin_option from

dba_role_privs@<DB_LINK> r, dba_users@<DB_LINK> u ',

'where u.username = r.grantee and r.granted_role not in (''DBA'', ''RESOURCE'',

''IMP_FULL_DATABASE'',''EXP_FULL_DATABASE'',''CONNECT'',''SNMPAGENT'') ','commit ','',

'Application Roles

- Every application must create distinct roles containing all necessary privileges for

application users and administrators

- All roles created and used by an application must be password protected

- All application users must be granted the appropriate application role

- No user may have an application role assigned as the default role');

/* The OPS_USERS monitor selectes all users that are authenticated externally */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('OPS_USERS','Users Using External Authentication',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''OPS_USERS'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1) ',

'select ''<DB_ID>'',''OPS_USERS'',sysdate,username, password from dba_users@<DB_LINK> ',

'where password=''EXTERNAL'' ','commit ','',

'OPS$ Accounts

- OPS$ accounts should not be used.');

/* The SYS_AUDIT1 monitor selects the location of the AUD$ table */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('SYS_AUDIT1','Audit Trail Location',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''SYS_AUDIT1'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1) ',

'select ''<DB_ID>'', ''SYS_AUDIT1'', sysdate, owner || ''.'' || table_name, tablespace_name from

dba_tables@<DB_LINK> ',

'where table_name=''AUD$'' and owner like ''SYS%'' ','commit ','',

Page 61: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 61

'Database Auditing Configuration

- The audit trail must be created in a separate and individual tablespace, it cannot

be stored in the SYSTEM tablespace.');

/* The SYS_AUDIT3 monitor selects all objects which are not audited for rename actions */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('SYS_AUDIT3','Audit Object Rename Options',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''SYS_AUDIT3'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1, value2) ',

'select ''<DB_ID>'', ''SYS_AUDIT3'', sysdate, owner, object_name, object_type from

dba_obj_audit_opts@<DB_LINK> ',

'where ren = ''-/-'' ','commit ','',

'Mandatory Auditing');

/* The SYS_AUDIT4 monitor selects the object level auditing options enabled on AUD$ */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('SYS_AUDIT4','Audit AUD$ Options',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''SYS_AUDIT4'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1, value2) ',

'select ''<DB_ID>'', ''SYS_AUDIT4'', sysdate, owner || ''.'' || object_name, object_type, alt ||

aud || com || del || gra || ind || ins || loc || ren || sel || upd || ref || exe from

dba_obj_audit_opts@<DB_LINK> ',

'where owner like ''SYS%'' and object_name=''AUD$'' and object_type=''TABLE'' ',

'commit ','',

'Mandatory Auditing');

/* The SYS_AUDIT5 monitor selects all privilege level audits enabled in the instance */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('SYS_AUDIT5','Audit Privilege Options',

Page 62: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 62

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''SYS_AUDIT5'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1, value2) ',

'select ''<DB_ID>'', ''SYS_AUDIT5'', sysdate, privilege, success, failure from

dba_priv_audit_opts@<DB_LINK> ',' ','commit ','',

'Mandatory Auditing');

/* The UTL_FILE monitor selects all users with EXECUTE privileges on the

UTL_FILE package */

insert into monitor

(monitor_id, name, prepare1_clause, prepare2_clause, insert_clause, select_clause,

where_clause, close1_clause, close2_clause, comment_text)

values

('UTL_FILE','Execute Privileges on UTL_FILE',

'delete from db_monitor_result where db_id=''<DB_ID>'' and monitor_id=''UTL_FILE'' ','',

'insert into db_monitor_result (db_id, monitor_id, run_time, parameter, value1) ',

'select ''<DB_ID>'', ''UTL_FILE'', sysdate, grantee, table_name from dba_tab_privs@<DB_LINK> ',

'where table_name=''UTL_FILE'' ','commit ','',

'Stored Procedures

- The UTL_FILE package must not be granted to PUBLIC');

Standard Criteria:

/*

Script 6: GuardDog Standard Criteria

This script creates the GuardDog standard criteria. A definition for each criteria

is inserted into the DB_MONITOR_CRITERIA table. You may wish to modify these criteria

to meet specific requirements of your system. For instance, you may wish to change

the "score" for each violation.

*/

/* Check users for unlimited idle time */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','IDLE_TIME','FORBIDDEN','%','UNLIMITED','','5',

'User has no idle timeout');

/* Make sure the audit_trail parameter is set to "db" */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','INIT_PARAM','REQUIRED','audit_trail','DB','FALSE','10',

'The audit_trail parameter must be set to ''db'' ');

/* Make sure the utl_file_dir parameter is not set to "*" */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','INIT_PARAM','FORBIDDEN','utl_file_dir','*','','10',

'UTL_FILE_DIR is set to ''*'' ');

/* Make sure the remote_os_authent parameter is set to "false" */

Page 63: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 63

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','INIT_PARAM','REQUIRED','remote_os_authent','FALSE','TRUE','10',

'The remote_os_authent parameter must be set to ''false'' ');

/* Make sure the resource_limit parameter is set to "true" */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','INIT_PARAM','REQUIRED','resource_limit','TRUE','FALSE','10',

'The resource_limit parameter must be set to ''true'' ');

/* Make sure the os_roles parameter is set to "false" */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','INIT_PARAM','REQUIRED','os_roles','FALSE','TRUE','10',

'The os_roles parameter must be set to ''false'' ');

/* Make sure the dblink_encrypt_login parameter is set to "false" */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','INIT_PARAM','REQUIRED','dblink_encrypt_login','TRUE','FALSE','10',

'The dblink_encrypt_login parameter must be set to ''true'' ');

/* Make sure the remote_os_roles parameter is set to "false" */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','INIT_PARAM','REQUIRED','remote_os_roles','FALSE','TRUE','10',

'The remote_os_roles parameter must be set to ''false'' ');

/* Check for any users assigned Alter or References privileges */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','OBJ_PRIVS1','FORBIDDEN','%','','','10',

'User has ALTER or REFERENCES privilege');

/* Check for any roles assigned Alter or References privileges */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','OBJ_PRIVS2','FORBIDDEN','%','','','5',

'Role has ALTER or REFERENCES privilege');

/* Check for any users assigned default Oracle roles */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','ORACLE_ROLES','FORBIDDEN','%','','','10',

'User/Role has restricted role');

/* Check for users with Admin privileges on system privileges/objects */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_ADMIN1','FORBIDDEN','%','','','10',

'User has ADMIN option on privilege/object');

/* Check for users with Admin privileges on default Oracle roles */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_ADMIN2','FORBIDDEN','%','','','10',

'User has ADMIN option on restricted role');

/* Check for required statement level audits */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED',

'ALTER SYSTEM','','','10','The ALTER SYSTEM statement must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED',

'NOT EXISTS','','','10','The NOT EXISTS statement must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED',

'SYSTEM AUDIT','','','10','The SYSTEM AUDIT statement must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED','TABLESPACE','','','10',

'The TABLESPACE statement must be audited');

Page 64: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 64

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED','TABLE','','','10',

'The TABLE statement must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED',

'DROP DATABASE LINK','','','5','The DROP DATABASE LINK privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED',

'GRANT TABLE','','','5','The GRANT TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED',

'DELETE TABLE','','','5','The DELETE TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED',

'CREATE SESSION','','','10','The CREATE SESSION statement must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED','USER','','','10',

'The USER statement must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED',

'SYSTEM GRANT','','','10','The SYSTEM GRANT statement must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT2','REQUIRED','INDEX','','','10',

'The INDEX statement must be audited');

/* Check for password protection on application roles */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','APP_ROLES1','REQUIRED','%','YES','','10',

'Application role is not password protected or missing');

/* Check for default enable on application roles, roles with no users assigned */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','APP_ROLES2','REQUIRED','%','','NO','5',

'No users assigned to application roles or role is enabled by default');

/* Check for users authenticated externally */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','OPS_USERS','FORBIDDEN','%','','','5',

'User is authenticated externally');

/* Check for presence of AUD$ in the SYSTEM tablespace */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT1','FORBIDDEN','%','SYSTEM','','10',

'The audit trail table is located in the SYSTEM tablespace ');

/* Check for objects not audited for rename */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT3','FORBIDDEN','%','','','1',

'This object is not audited for RENAME ');

/* Check for access level audits on the AUD$ table */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT4','REQUIRED','%','TABLE',

'A/AA/AA/AA/AA/AA/AA/AA/AA/AA/AA/A-/--/-','10','The audit trail table AUD$ must be audited');

/* Check for required privilege level audits */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ANALYZE ANY','','','5','The ANALYZE ANY privilege must be audited');

Page 65: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 65

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'SELECT ANY SEQUENCE','','','5','The SELECT ANY SEQUENCE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP ANY SEQUENCE','','','5','The DROP ANY SEQUENCE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ALTER ANY SEQUENCE','','','5','The ALTER ANY SEQUENCE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE ANY SEQUENCE','','','5','The CREATE ANY SEQUENCE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE SESSION','','','5','The CREATE SESSION privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'RESTRICTED SESSION','','','5','The RESTRICTED SESSION privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP ROLLBACK SEGMENT','','','5','The DROP ROLLBACK SEGMENT privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'GRANT ANY ROLE','','','5','The GRANT ANY ROLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'MANAGE TABLESPACE','','','5','The MANAGE TABLESPACE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DELETE ANY TABLE','','','5','The DELETE ANY TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'UPDATE ANY TABLE','','','5','The UPDATE ANY TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'INSERT ANY TABLE','','','5','The INSERT ANY TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'SELECT ANY TABLE','','','5','The SELECT ANY TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'COMMENT ANY TABLE','','','5','The COMMENT ANY TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'LOCK ANY TABLE','','','5','The LOCK ANY TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP ANY TABLE','','','5','The DROP ANY TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP PUBLIC SYNONYM','','','5','The DROP PUBLIC SYNONYM privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE PUBLIC SYNONYM','','','5','The CREATE PUBLIC SYNONYM privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

Page 66: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 66

'CREATE PUBLIC DATABASE LINK','','','5',

'The CREATE PUBLIC DATABASE LINK privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE DATABASE LINK','','','5','The CREATE DATABASE LINK privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP ANY VIEW','','','5','The DROP ANY VIEW privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE ANY VIEW','','','5','The CREATE ANY VIEW privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP USER','','','5','The DROP USER privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ALTER USER','','','5','The ALTER USER privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'BECOME USER','','','5','The BECOME USER privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE USER','','','5','The CREATE USER privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP ANY TRIGGER','','','5','The DROP ANY TRIGGER privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ALTER ANY TRIGGER','','','5','The ALTER ANY TRIGGER privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE ANY TRIGGER','','','5','The CREATE ANY TRIGGER privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'FORCE ANY TRANSACTION','','','5','The FORCE ANY TRANSACTION privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'FORCE TRANSACTION','','','5','The FORCE TRANSACTION privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'UNLIMITED TABLESPACE','','','5','The UNLIMITED TABLESPACE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'BACKUP ANY TABLE','','','5','The BACKUP ANY TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ALTER ANY TABLE','','','5','The ALTER ANY TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE ANY TABLE','','','5','The CREATE ANY TABLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ALTER SYSTEM','','','5','The ALTER SYSTEM privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP ANY SYNONYM','','','5','The DROP ANY SYNONYM privilege must be audited');

Page 67: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 67

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE ANY SYNONYM','','','5','The CREATE ANY SYNONYM privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP ANY SNAPSHOT','','','5','The DROP ANY SNAPSHOT privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ALTER ANY SNAPSHOT','','','5','The ALTER ANY SNAPSHOT privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP ANY ROLE','','','5','The DROP ANY ROLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ALTER ANY ROLE','','','5','The ALTER ANY ROLE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP PUBLIC SYNONYM','','','5','The DROP PUBLIC SYNONYM privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP PUBLIC DATABASE LINK','','','5','The DROP PUBLIC DATABASE LINK privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ALTER RESOURCE COST','','','5','The ALTER RESOURCE COST privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP PROFILE','','','5','The DROP PROFILE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ALTER PROFILE','','','5','The ALTER PROFILE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE PROFILE','','','5','The CREATE PROFILE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'EXECUTE ANY PROCEDURE','','','5','The EXECUTE ANY PROCEDURE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'DROP ANY PROCEDURE','','','5','The DROP ANY PROCEDURE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'ALTER ANY PROCEDURE','','','5','The ALTER ANY PROCEDURE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'CREATE ANY PROCEDURE','','','5','The CREATE ANY PROCEDURE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED',

'GRANT ANY PRIVILEGE','','','5','The GRANT ANY PRIVILEGE privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED','DROP ANY INDEX','','','5',

'The DROP ANY INDEX privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED','ALTER ANY INDEX','','','5',

'The ALTER ANY INDEX privilege must be audited');

Page 68: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 68

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED','CREATE ANY INDEX','','','5',

'The CREATE ANY INDEX privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED','ALTER ANY CLUSTER','','','5',

'The ALTER ANY CLUSTER privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED','DROP ANY CLUSTER','','','5',

'The DROP ANY CLUSTER privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED','AUDIT ANY','','','5',

'The AUDIT ANY privilege must be audited');

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_AUDIT5','REQUIRED','ALTER DATABASE','','','5',

'The ALTER DATABASE privilege must be audited');

/* Check for users with restricted privileges */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_PRIVS1','FORBIDDEN','%','','','10',

'User has restricted privilege');

/* Check for roles with restricted privileges */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','SYS_PRIVS2','FORBIDDEN','%','','','5',

'Role has restricted privilege');

/* Check for users with Execute privileges on UTL_FILE */

insert into db_monitor_criteria (db_id, monitor_id, criteria_type, parameter, value1, value2,

score, comment_text) values ('DEFAULT','UTL_FILE','FORBIDDEN','%','','','5',

'User has EXECUTE on UTL_FILE');

Sam ple Criteria Exceptions: Provided as an example of how to define exceptions for an actual database.

/*

Script 7: GuardDog Sample Criteria Exceptions

This script is a sample of rows that can be inserted into the DB_MONITOR_CRITERIA table

to suppress violations from the final report or explain exceptions to basic security

policy. Use these samples as a guide to creating your own exceptions. Note that the

score column for each exception is set to "0".

*/

/* The following two exceptions are for users who have been granted standard Oracle

roles like DBA and EXP_FULL_DATABASE */

insert into db_monitor_criteria

(db_id, monitor_id, criteria_type, parameter, value1, value2, score, comment_text)

values

('TEST_DB','ORACLE_ROLES','SUPPRESSED','FRED1','DBA','','0',

'FRED1 is an authorized DBA account');

insert into db_monitor_criteria

(db_id, monitor_id, criteria_type, parameter, value1, value2, score, comment_text)

values

('TEST_DB','ORACLE_ROLES','SUPPRESSED','OPS$ORACLE','EXP_FULL_DATABASE','','0',

'OPS$ORACLE is used to perform automated backups');

/* The following three exceptions are for users with special system privileges */

Page 69: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 69

insert into db_monitor_criteria

(db_id, monitor_id, criteria_type, parameter, value1, value2, score, comment_text)

values

('TEST_DB','SYS_PRIVS1','SUPPRESSED','OPS$ORACLE','SELECT ANY TABLE','','0',

'OPS$ORACLE is used to perform automated DBA procedures');

insert into db_monitor_criteria

(db_id, monitor_id, criteria_type, parameter, value1, value2, score, comment_text)

values

('TEST_DB','SYS_PRIVS1','SUPPRESSED','CONSOLE1','UNLIMITED TABLESPACE','','0',

'CONSOLE1 is an authorized DBA account');

insert into db_monitor_criteria

(db_id, monitor_id, criteria_type, parameter, value1, value2, score, comment_text)

values

('TEST_DB','SYS_PRIVS1','SUPPRESSED','EAGLE1','CREATE SESSION','','0',

'EAGLE1 is used to perform automated DBA procedures');

GuardDog Reports

On Screen and ASCII File Reports PL/SQL Package:

/*

Script 3: GuardDog Report PL/SQL Package

This script creates the GUARD_DOG_REPORT package which produces the basic GuardDog

evaluation reports. This package requires that all of the GuardDog objects have

already been created using Script 1. This script should be run in the GuardDog

schema, although you may grant execute privileges on this package to other users.

The GUARD_DOG_REPORT package is composed of two procedures. PRINT_RPT produces the

print-to-screen version of the report. PRINT_FILE produces the write-to-file version

of the report.

*/

CREATE OR REPLACE PACKAGE GUARD_DOG_REPORT AS

procedure print_rpt (DBID in VARCHAR2);

procedure print_file (DBID in VARCHAR2, FILENM in VARCHAR2, FILEPATH in VARCHAR2);

END GUARD_DOG_REPORT;

CREATE OR REPLACE PACKAGE BODY GUARD_DOG_REPORT AS

/*

Procedure PRINT_RPT retrieves and formats the data in the db_monitor_report

table for the designated database. To view the report, you must set

SERVEROUTPUT on in SQL*Plus, Server Manager, or SQL Worksheet.

*/

PROCEDURE PRINT_RPT (DBID in VARCHAR2) AS

cursor C_DB_MONITOR_SECTION is

Page 70: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 70

select distinct substr(m.comment_text,1,500) from monitor m, db_monitor d

where m.monitor_id = d.monitor_id and d.active_yn='Y';

cursor C_DB_MONITOR_PARA (COMMENT_TXT VARCHAR2) is

select * from monitor where substr(comment_text,1,500)=COMMENT_TXT;

cursor C_DB_MONITOR_REPORT (DBID VARCHAR2, MON_ID VARCHAR2) is

select * from db_monitor_report

where db_id=DBID and monitor_id=MON_ID and

comment_text <> 'No evaluation criteria exist for this parameter';

cursor C_DB_MONITOR_SUPRESS (DBID VARCHAR2, MON_ID VARCHAR2) is

select * from db_monitor_criteria

where db_id=DBID and monitor_id=MON_ID and

criteria_type='SUPPRESSED';

monitor_rec MONITOR%ROWTYPE;

report_rec DB_MONITOR_REPORT%ROWTYPE;

supress_rec DB_MONITOR_CRITERIA%ROWTYPE;

section_header varchar2(500);

pos number;

rpt_date varchar2(30);

audit_score number;

BEGIN

select to_char(max(run_time),'DD-MON-YY HH24:MI:SS') into rpt_date

from db_monitor_result where db_id=DBID;

/* Print report header */

dbms_output.put_line('Audit Evaluation Summary Report for ' || DBID);

dbms_output.put_line('As of: ' || rpt_date);

dbms_output.new_line;

/* Get list of section headers (comments in monitor table) */

open C_DB_MONITOR_SECTION;

loop

fetch C_DB_MONITOR_SECTION into section_header;

exit when C_DB_MONITOR_SECTION%NOTFOUND;

/* Print section header */

pos := instr(section_header,chr(10),200);

dbms_output.put_line(substr(section_header,1,pos-1));

dbms_output.put_line(substr(section_header,pos+1,pos+255));

dbms_output.new_line;

Page 71: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 71

/* Get list of monitors that belong in section */

open C_DB_MONITOR_PARA(section_header);

loop

fetch C_DB_MONITOR_PARA into monitor_rec;

exit when C_DB_MONITOR_PARA%NOTFOUND;

/* Get report data for each monitor */

open C_DB_MONITOR_REPORT (DBID, monitor_rec.monitor_id);

loop

fetch C_DB_MONITOR_REPORT into report_rec;

exit when C_DB_MONITOR_REPORT%NOTFOUND;

/* Print formatted report data for current monitor */

dbms_output.put_line (rpad(nvl(substr(report_rec.parameter,1,30),' '),33) ||

rpad(nvl(substr(report_rec.value1,1,20),' '),23) ||

rpad(nvl(substr(report_rec.value2,1,20),' '),23) ||

substr(report_rec.comment_text,1,100));

end loop;

close C_DB_MONITOR_REPORT;

dbms_output.new_line;

open C_DB_MONITOR_SUPRESS (DBID, monitor_rec.monitor_id);

loop

fetch C_DB_MONITOR_SUPRESS into supress_rec;

exit when C_DB_MONITOR_SUPRESS%NOTFOUND;

/* Print formatted report data for current monitor */

dbms_output.put_line (rpad(nvl(substr(supress_rec.parameter,1,30),' '),33) ||

rpad(nvl(substr(supress_rec.value1,1,20),' '),23) ||

rpad(nvl(substr(supress_rec.value2,1,20),' '),23) ||

substr(supress_rec.comment_text,1,100));

end loop;

close C_DB_MONITOR_SUPRESS;

dbms_output.new_line;

end loop;

close C_DB_MONITOR_PARA;

dbms_output.new_line;

/* Display section total vulnerability score */

select sum(score) into audit_score from db_monitor_report r, monitor m

where r.db_id=DBID and r.monitor_id=m.monitor_id and

Page 72: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 72

m.comment_text=section_header;

dbms_output.put_line(' Section Score: ' || nvl(audit_score,'0'));

dbms_output.new_line;

end loop;

/* Display database total vulnerability score */

select sum(score) into audit_score from db_monitor_report

where db_id=DBID;

dbms_output.put_line('Total Score: ' || nvl(audit_score,'0'));

dbms_output.new_line;

END PRINT_RPT;

/*

Procedure PRINT_FILE retrieves and formats the data in the db_monitor_report

table for the designated database. The report is written directly into a specified

file by the UTL_FILE package.

*/

PROCEDURE PRINT_FILE (DBID in VARCHAR2, FILENM in VARCHAR2,

FILEPATH in VARCHAR2) AS

file_handle UTL_FILE.FILE_TYPE;

cursor C_DB_MONITOR_SECTION is

select distinct substr(m.comment_text,1,500) from monitor m, db_monitor d

where m.monitor_id = d.monitor_id and d.active_yn='Y';

cursor C_DB_MONITOR_PARA (COMMENT_TXT VARCHAR2) is

select * from monitor where substr(comment_text,1,500)=COMMENT_TXT;

cursor C_DB_MONITOR_REPORT (DBID VARCHAR2, MON_ID VARCHAR2) is

select * from db_monitor_report

where db_id=DBID and monitor_id=MON_ID and

comment_text <> 'No evaluation criteria exist for this parameter';

cursor C_DB_MONITOR_SUPRESS (DBID VARCHAR2, MON_ID VARCHAR2) is

select * from db_monitor_criteria

where db_id=DBID and monitor_id=MON_ID and

criteria_type='SUPPRESSED';

monitor_rec MONITOR%ROWTYPE;

report_rec DB_MONITOR_REPORT%ROWTYPE;

supress_rec DB_MONITOR_CRITERIA%ROWTYPE;

section_header varchar2(500);

pos number;

rpt_date varchar2(30);

Page 73: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 73

audit_score number;

BEGIN

/* Open file for output */

file_handle := utl_file.fopen (FILEPATH,FILENM,'W');

select to_char(max(run_time),'DD-MON-YY HH24:MI:SS') into rpt_date

from db_monitor_result where db_id=DBID;

/* Print report header */

utl_file.put_line(file_handle,'Audit Evaluation Summary Report for ' || DBID);

utl_file.put_line(file_handle,'As of: ' || rpt_date);

utl_file.new_line(file_handle);

/* Get list of section headers (comments in monitor table) */

open C_DB_MONITOR_SECTION;

loop

fetch C_DB_MONITOR_SECTION into section_header;

exit when C_DB_MONITOR_SECTION%NOTFOUND;

/* Print section header */

pos := instr(section_header,chr(10),200);

utl_file.put_line(file_handle,substr(section_header,1,pos-1));

utl_file.put_line(file_handle,substr(section_header,pos+1,pos+255));

utl_file.new_line(file_handle);

/* Get list of monitors that belong in section */

open C_DB_MONITOR_PARA(section_header);

loop

fetch C_DB_MONITOR_PARA into monitor_rec;

exit when C_DB_MONITOR_PARA%NOTFOUND;

/* Get report data for each monitor */

open C_DB_MONITOR_REPORT (DBID, monitor_rec.monitor_id);

loop

fetch C_DB_MONITOR_REPORT into report_rec;

exit when C_DB_MONITOR_REPORT%NOTFOUND;

/* Print formatted report data for current monitor */

utl_file.put_line (file_handle,

rpad(nvl(substr(report_rec.parameter,1,30),' '),33) ||

rpad(nvl(substr(report_rec.value1,1,20),' '),23) ||

Page 74: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 74

rpad(nvl(substr(report_rec.value2,1,20),' '),23) ||

substr(report_rec.comment_text,1,100));

end loop;

close C_DB_MONITOR_REPORT;

utl_file.new_line(file_handle);

open C_DB_MONITOR_SUPRESS (DBID, monitor_rec.monitor_id);

loop

fetch C_DB_MONITOR_SUPRESS into supress_rec;

exit when C_DB_MONITOR_SUPRESS%NOTFOUND;

/* Print formatted report data for current monitor */

utl_file.put_line (file_handle,

rpad(nvl(substr(supress_rec.parameter,1,30),' '),33) ||

rpad(nvl(substr(supress_rec.value1,1,20),' '),23) ||

rpad(nvl(substr(supress_rec.value2,1,20),' '),23) ||

substr(supress_rec.comment_text,1,100));

end loop;

close C_DB_MONITOR_SUPRESS;

utl_file.new_line(file_handle);

end loop;

close C_DB_MONITOR_PARA;

utl_file.new_line(file_handle);

/* Display section total vulnerability score */

select sum(score) into audit_score from db_monitor_report r, monitor m

where r.db_id=DBID and r.monitor_id=m.monitor_id and

m.comment_text=section_header;

utl_file.put_line(file_handle,' Section Score: ' || nvl(audit_score,'0'));

utl_file.new_line(file_handle);

end loop;

/* Display database total vulnerability score */

select sum(score) into audit_score from db_monitor_report where db_id=DBID;

utl_file.put_line(file_handle,'Total Score: ' || nvl(audit_score,'0'));

utl_file.new_line(file_handle);

utl_file.fclose(file_handle);

EXCEPTION

WHEN UTL_FILE.INVALID_PATH THEN

utl_file.fclose(file_handle);

WHEN UTL_FILE.READ_ERROR THEN

Page 75: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 75

utl_file.fclose(file_handle);

WHEN UTL_FILE.WRITE_ERROR THEN

utl_file.fclose(file_handle);

WHEN OTHERS THEN

utl_file.fclose(file_handle);

END PRINT_RPT_FILE;

END GUARD_DOG_REPORT;

Web PL/SQL Package:

/*

Script 4: GuardDog Web PL/SQL Package

This script creates the GUARD_DOG_WEB package which produces the HTML GuardDog

evaluation reports. This package requires that all of the GuardDog objects have

already been created using Script 1. This package also requires the prior

installation of the Oracle WebServer PL/SQL Web Toolkit and the OWA_CHART package.

This script should be run in the GuardDog schema, although you may grant execute

privileges on this package to other users (specifically the web server schema).

The GUARD_DOG_WEB package is composed of three procedures. QUERY_WEB produces a

drop-down list style query that allows users to generate a detailed report on the

selected database. SUMMARY_WEB produces a bar chart summary of total scores for

all evaluated databases, and also allows access to database details. PRINT_WEB

generates the same detailed evaluation report as GUARD_DOG_REPORT.

*/

CREATE OR REPLACE PACKAGE GUARD_DOG_WEB AS

procedure query_web;

procedure summary_web;

procedure print_web (DBID in VARCHAR2);

END GUARD_DOG_WEB;

CREATE OR REPLACE PACKAGE BODY GUARD_DOG_WEB AS

/*

Procedure QUERY_WEB presents the user with a drop-down list of all databases

listed in the database table. The user selects the desired database from the

list and clicks on the the "Submit" button. "Submit" called the print_web

procedure which prints a detailed report for the selected database.

*/

PROCEDURE QUERY_WEB AS

Page 76: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 76

cursor dblist is

select distinct db_id, db_name from eagle.database order by db_name;

cursor score_sum is

select d.db_name, sum(r.score) totscore

from eagle.database d, eagle.db_monitor_report r

where d.db_id = r.db_id

group by d.db_name;

BEGIN

/* Open HTML document and print header */

htp.htmlOpen;

htp.headOpen;

htp.title('Security Evaluation Summary Reports');

htp.headClose;

/* Open the body of the HTML document. You may want to change default colors, etc. */

htp.bodyOpen('','BGCOLOR="#000066" TEXT="#ffffe8" LINK="#ccffff" VLINK="#33ccff"');

htp.header(1,'Security Evaluation Summary Reports');

htp.hr;

/*

Open the form with the drop down list.

You may have to change the URL below to conform to your local web site.

*/

htp.formOpen('/webaudit/owa/guard_dog_web.print_web','POST');

htp.print('<B>Select Report Criteria:</B><P>');

htp.tableOpen;

/* Create drop down list from query on database table */

htp.print('<TR><TD WIDTH="150">Database Name:</TD><TD>');

htp.formSelectOpen('dbid');

for dc in dblist loop

htp.formSelectOption(dc.db_name,'','value="'||dc.db_id||'"');

end loop;

htp.formSelectClose;

htp.print('</TD></TR>');

htp.tableClose;

htp.para;

/* Place form buttons and close form */

Page 77: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 77

htp.formSubmit('','Submit');

htp.formReset('Reset');

htp.formClose;

htp.hr;

/* Create tabular score summary from query on db_monitor_report */

htp.tableOpen('BORDER');

htp.tableRowOpen;

htp.tableHeader('Database Name');

htp.tableHeader('Score');

htp.tableRowClose;

for sum_rec in score_sum loop

/* Print formatted report data for current monitor */

htp.tableRowOpen;

htp.tableData(sum_rec.db_name);

htp.tableData(sum_rec.totscore);

htp.tableRowClose;

end loop;

htp.tableClose;

/* Insert your generic page footer here. Mine is included as an example. */

htp.hr;

htp.print('<P><FONT SIZE=2><CITE>');

htp.anchor('/','<IMG BORDER=0 SRC="/images/home-b.jpg">');

htp.anchor('mailto:[email protected]','<IMG BORDER=0 SRC="/images/mail-b.jpg">');

htp.para;

htp.print('Webmaster: Mr. Pete Magee<br>');

htp.print('email: <A HREF="mailto:[email protected]">');

htp.print('[email protected]</A><br></CITE></FONT><P>');

htp.img('/images/tag1.gif','bottom','Generated by Oracle WebServer');

/* Close body and HTML document */

htp.bodyClose;

htp.htmlClose;

END QUERY_RPT_WEB;

/*

Procedure SUMMARY_WEB presents the user with a bar chart list of all databases

listed in the db_monitor_report table with their total scores. The user selects the

Page 78: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 78

desired database from the list and clicks on its name (the name is a link). This

calls the PRINT_WEB procedure which prints a detailed report for the selected

database.

*/

PROCEDURE SUMMARY_WEB AS

cursor dblist is

select distinct db_id, db_name from eagle.database order by db_name;

cursor score_sum is

select d.db_name, sum(r.score) totscore

from eagle.database d, eagle.db_monitor_report r

where d.db_id = r.db_id

group by d.db_name;

querystr varchar2(2000);

BEGIN

/* Open HTML document and print header */

htp.htmlOpen;

htp.headOpen;

htp.title('Audit Evaluation Summary Reports');

htp.headClose;

/* Open the body of the HTML document. You may want to change default colors, etc. */

htp.bodyOpen('','BGCOLOR="#000066" TEXT="#ffffe8" LINK="#ccffff" VLINK="#33ccff"');

htp.header(1,'Audit Evaluation Summary Reports');

/* Open the table that will frame the bar chart */

htp.tableOpen('BORDER','','','','WIDTH="100%"');

htp.tableRowOpen;

htp.print('<TD>');

/*

Define the query string that will be used to generate the bar chart from OWA_CHART.

You may want to change the URL embedded in the query to fit your local web site.

*/

querystr := 'select ''/webaudit/owa/guard_dog_web.print_web?dbid=''||d.db_id the_link,

d.db_name the_text, sum(r.score) the_value

from eagle.database d, eagle.db_monitor_report r

where d.db_id = r.db_id

group by ''/webaudit/owa/guard_dog_web.print_web?dbid=''||d.db_id, d.db_name';

Page 79: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 79

/*

Call OWA_CHART. You may have to change the schema, depending on your local

configuration and which user owns the OWA_CHART package. It works best if

all of these packages are owned by the same user.

*/

eagle.owa_chart.show_chart (

chart_type => 'HBAR',

bar_image => 'grey.gif',

show_summary => '',

axis => 'ZERO',

font_size => '+0',

chart_title =>'Total Scores for each Database',

q => querystr);

htp.print('</TD>');

htp.tableRowClose;

htp.tableClose;

/* Insert your generic page footer here. Mine is included as an example. */

htp.hr;

htp.print('<P><FONT SIZE=2><CITE>');

htp.anchor('/','<IMG BORDER=0 SRC="/images/home-b.jpg">');

htp.anchor('/admin/index.html','<IMG BORDER=0 SRC="/images/up-b.jpg">');

htp.anchor('mailto:[email protected]','<IMG BORDER=0 SRC="/images/mail-b.jpg">');

htp.para;

htp.print('Webmaster: Mr. Pete Magee<br>');

htp.print('email: <A HREF="mailto:[email protected]">');

htp.print('[email protected]</A><br></CITE></FONT><P>');

htp.img('/images/tag1.gif','bottom','Generated by Oracle WebServer');

/* Close body and HTML document */

htp.bodyClose;

htp.htmlClose;

END SUMMARY_WEB;

/*

Procedure PRINT_WEB prints the detailed evaluation report for the selected database.

*/

PROCEDURE PRINT_WEB (DBID in VARCHAR2) AS

Page 80: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 80

cursor C_DB_MONITOR_SECTION is

select distinct substr(m.comment_text,1,500)

from eagle.monitor m, eagle.db_monitor d

where m.monitor_id = d.monitor_id and d.active_yn='Y';

cursor C_DB_MONITOR_PARA (COMMENT_TXT VARCHAR2) is

select * from eagle.monitor where substr(comment_text,1,500)=COMMENT_TXT;

cursor C_DB_MONITOR_REPORT (DBID VARCHAR2, MON_ID VARCHAR2) is

select * from eagle.db_monitor_report

where db_id=DBID and monitor_id=MON_ID and

comment_text <> 'No evaluation criteria exist for this parameter';

cursor C_DB_MONITOR_SUPRESS (DBID VARCHAR2, MON_ID VARCHAR2) is

select * from db_monitor_criteria

where db_id=DBID and monitor_id=MON_ID and

criteria_type='SUPPRESSED';

monitor_rec MONITOR%ROWTYPE;

report_rec DB_MONITOR_REPORT%ROWTYPE;

supress_rec DB_MONITOR_CRITERIA%ROWTYPE;

section_header varchar2(500);

pos number;

dbname varchar2(10);

monitorname varchar2(20);

rpt_date varchar2(30);

audit_score number;

BEGIN

/* Open HTML document and print header */

htp.htmlOpen;

htp.headOpen;

htp.title('Audit Evaluation Summary Report');

htp.headClose;

/* Open the body of the HTML document. You may want to change default colors, etc. */

htp.bodyOpen('','BGCOLOR="#000066" TEXT="#ffffe8" LINK="#ccffff" VLINK="#33ccff"');

htp.header(1, 'Audit Evaluation Summary Report');

/* Get the last run timestamp from db_monitor_report for the specified database */

select to_char(max(run_time),'DD-MON-YY HH24:MI:SS') into rpt_date

from eagle.db_monitor_result where db_id=DBID;

/* Print report header */

htp.header(2,'Database: ' || DBID);

Page 81: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 81

htp.bold('As of: ' || rpt_date);

htp.para;

/* Get list of section headers (comments in monitor table) */

open C_DB_MONITOR_SECTION;

loop

fetch C_DB_MONITOR_SECTION into section_header;

exit when C_DB_MONITOR_SECTION%NOTFOUND;

htp.tableOpen('BORDER','','','','WIDTH="100%"');

/* Print section header */

htp.tableRowOpen;

htp.tableData(htf.bold('<PRE>' || section_header || '</PRE>'),'left','','','','4');

htp.tableRowClose;

htp.tableRowOpen;

htp.tableHeader('Parameter');

htp.tableHeader('Value1');

htp.tableHeader('Value2');

htp.tableHeader('Comment');

htp.tableRowClose;

/* Get list of monitors that belong in section */

open C_DB_MONITOR_PARA(section_header);

loop

fetch C_DB_MONITOR_PARA into monitor_rec;

exit when C_DB_MONITOR_PARA%NOTFOUND;

/* Get report data for each monitor */

open C_DB_MONITOR_REPORT (DBID, monitor_rec.monitor_id);

loop

fetch C_DB_MONITOR_REPORT into report_rec;

exit when C_DB_MONITOR_REPORT%NOTFOUND;

/* Print formatted report data for current monitor */

htp.tableRowOpen;

htp.tableData(report_rec.parameter);

htp.tableData(report_rec.value1);

htp.tableData(report_rec.value2);

htp.tableData(report_rec.comment_text);

htp.tableRowClose;

Page 82: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code / Page 82

end loop;

close C_DB_MONITOR_REPORT;

open C_DB_MONITOR_SUPRESS (DBID, monitor_rec.monitor_id);

loop

fetch C_DB_MONITOR_SUPRESS into supress_rec;

exit when C_DB_MONITOR_SUPRESS%NOTFOUND;

/* Print formatted report data for current monitor */

htp.tableRowOpen;

htp.tableData(supress_rec.parameter);

htp.tableData(supress_rec.value1);

htp.tableData(supress_rec.value2);

htp.tableData(supress_rec.comment_text);

htp.tableRowClose;

end loop;

close C_DB_MONITOR_SUPRESS;

end loop;

close C_DB_MONITOR_PARA;

/* Display section total vulnerability score */

select sum(score) into audit_score from eagle.db_monitor_report r, monitor m

where r.db_id=DBID and r.monitor_id=m.monitor_id and

m.comment_text=section_header;

htp.tableRowOpen;

htp.tableData(htf.bold('Section Score: ' || nvl(audit_score,'0')),

'left','','','','4');

htp.tableRowClose;

htp.tableClose;

htp.para;

end loop;

/* Display database total vulnerability score */

select sum(score) into audit_score from eagle.db_monitor_report

where db_id=DBID;

htp.header(3,'Total Score: ' || audit_score);

/* Insert your generic page footer here. Mine is included as an example. */

htp.hr;

Page 83: Enhancing Database Security: Concepts and Tools for · PDF fileEnhancing Database Security: Concepts and Tools for ... DROP PUBLIC DATAB ASE LINK LOCK ANY TABLE CREATE PUBLIC SYNON

Mini-Lesson M6, Scripts & Source Code/ Page 83

htp.print('<P><FONT SIZE=2><CITE>');

htp.anchor('/','<IMG BORDER=0 SRC="/images/home-b.jpg">');

htp.anchor('/webaudit/owa/guard_dog_web.summary_web',

'<IMG BORDER=0 SRC="/images/up-b.jpg">');

htp.anchor('mailto:[email protected]','<IMG BORDER=0 SRC="/images/mail-b.jpg">');

htp.para;

htp.print('Webmaster: Mr. Pete Magee<br>');

htp.print('email: <A HREF="mailto:[email protected]">');

htp.print('[email protected]</A><br></CITE></FONT><P>');

htp.img('/images/tag1.gif','bottom','Generated by Oracle WebServer');

/* Close body and HTML document */

htp.bodyClose;

htp.htmlClose;

END PRINT_WEB;

END GUARD_DOG_WEB;