Audit and Compliance Scripts
Audit and Compliance Scripts
Section titled “Audit and Compliance Scripts”Comprehensive scripts for implementing database auditing, monitoring user activities, and ensuring compliance with security policies.
Unified Audit Setup
Section titled “Unified Audit Setup”Enable Unified Auditing
Section titled “Enable Unified Auditing”-- Check current audit statusSELECT parameter, valueFROM v$optionWHERE parameter = 'Unified Auditing';
-- Create unified audit policy for sensitive operationsCREATE AUDIT POLICY sensitive_operations_policy PRIVILEGES CREATE TABLE, DROP TABLE, ALTER TABLE, CREATE USER, DROP USER, ALTER USER, CREATE ROLE, DROP ROLE, GRANT ANY PRIVILEGE, GRANT ANY ROLE ACTIONS DELETE ON hr.employees, UPDATE ON hr.employees, INSERT ON hr.employees, SELECT ON hr.salary_details ROLES DBA, HR_ADMIN;
-- Enable the audit policyAUDIT POLICY sensitive_operations_policy;
-- Create policy for failed login attemptsCREATE AUDIT POLICY failed_login_policy ACTIONS LOGON WHEN 'SYS_CONTEXT(''USERENV'', ''AUTHENTICATION_TYPE'') != ''DATABASE''' EVALUATE PER SESSION;
AUDIT POLICY failed_login_policy WHENEVER NOT SUCCESSFUL;
User Activity Audit Policy
Section titled “User Activity Audit Policy”-- Create comprehensive user activity auditCREATE AUDIT POLICY user_activity_policy ACTIONS SELECT, INSERT, UPDATE, DELETE, EXECUTE WHEN 'SYS_CONTEXT(''USERENV'', ''SESSION_USER'') NOT IN (''SYS'', ''SYSTEM'')' EVALUATE PER STATEMENT;
-- Apply policy to specific usersAUDIT POLICY user_activity_policy BY users_to_audit;
-- Apply policy to specific schemasAUDIT POLICY user_activity_policy ON hr.employees, hr.departments;
Traditional Auditing (Pre-12c)
Section titled “Traditional Auditing (Pre-12c)”Standard Audit Configuration
Section titled “Standard Audit Configuration”-- Enable standard auditingALTER SYSTEM SET audit_trail = DB_EXTENDED SCOPE = SPFILE;-- Restart database after setting
-- Audit user logon/logoffAUDIT SESSION;
-- Audit DDL operationsAUDIT CREATE TABLE, ALTER TABLE, DROP TABLE BY ACCESS;AUDIT CREATE USER, ALTER USER, DROP USER BY ACCESS;
-- Audit DML on sensitive tablesAUDIT SELECT, INSERT, UPDATE, DELETE ON hr.employees BY ACCESS;AUDIT SELECT ON hr.salary_details BY ACCESS WHENEVER SUCCESSFUL;
-- Audit privilege usageAUDIT CREATE ANY TABLE BY ACCESS;AUDIT SELECT ANY TABLE BY ACCESS;AUDIT GRANT ANY PRIVILEGE BY ACCESS;
Audit Trail Analysis
Section titled “Audit Trail Analysis”Unified Audit Trail Queries
Section titled “Unified Audit Trail Queries”-- Recent audit events summarySELECT event_timestamp, dbusername, action_name, object_schema, object_name, sql_text, return_code, client_program_name, os_username, userhostFROM unified_audit_trailWHERE event_timestamp > SYSTIMESTAMP - INTERVAL '24' HOURORDER BY event_timestamp DESCFETCH FIRST 100 ROWS ONLY;
-- Failed login attemptsSELECT event_timestamp, dbusername, os_username, userhost, authentication_type, action_name, return_code, COUNT(*) OVER ( PARTITION BY dbusername, userhost ORDER BY event_timestamp RANGE BETWEEN INTERVAL '1' HOUR PRECEDING AND CURRENT ROW ) as attempts_per_hourFROM unified_audit_trailWHERE action_name = 'LOGON' AND return_code != 0 AND event_timestamp > SYSTIMESTAMP - INTERVAL '7' DAYORDER BY event_timestamp DESC;
-- Privilege usage analysisSELECT dbusername, used_privilege, object_schema, object_name, COUNT(*) as usage_count, COUNT(DISTINCT TRUNC(event_timestamp)) as days_used, MIN(event_timestamp) as first_used, MAX(event_timestamp) as last_usedFROM unified_audit_trailWHERE used_privilege IS NOT NULL AND event_timestamp > SYSTIMESTAMP - INTERVAL '30' DAYGROUP BY dbusername, used_privilege, object_schema, object_nameORDER BY usage_count DESC;
DDL Change Tracking
Section titled “DDL Change Tracking”-- Track schema changesSELECT event_timestamp, dbusername, action_name, object_schema, object_name, object_type, sql_text, client_program_nameFROM unified_audit_trailWHERE action_name IN ( 'CREATE TABLE', 'ALTER TABLE', 'DROP TABLE', 'CREATE INDEX', 'DROP INDEX', 'CREATE VIEW', 'DROP VIEW', 'CREATE PROCEDURE', 'CREATE FUNCTION', 'CREATE PACKAGE') AND event_timestamp > SYSTIMESTAMP - INTERVAL '7' DAYORDER BY event_timestamp DESC;
-- Track permission changesSELECT event_timestamp, dbusername, action_name, object_schema, object_name, target_user, sql_textFROM unified_audit_trailWHERE action_name IN ('GRANT', 'REVOKE') AND event_timestamp > SYSTIMESTAMP - INTERVAL '30' DAYORDER BY event_timestamp DESC;
Compliance Reporting
Section titled “Compliance Reporting”User Access Report
Section titled “User Access Report”-- Comprehensive user access reportWITH user_privs AS ( SELECT grantee, privilege, admin_option, 'SYSTEM' as priv_type FROM dba_sys_privs WHERE grantee NOT IN ('SYS', 'SYSTEM', 'DBSNMP', 'XDB')
UNION ALL
SELECT grantee, owner || '.' || table_name || ' (' || privilege || ')' as privilege, grantable as admin_option, 'OBJECT' as priv_type FROM dba_tab_privs WHERE grantee NOT IN ('SYS', 'SYSTEM', 'DBSNMP', 'XDB')
UNION ALL
SELECT grantee, granted_role as privilege, admin_option, 'ROLE' as priv_type FROM dba_role_privs WHERE grantee NOT IN ('SYS', 'SYSTEM', 'DBSNMP', 'XDB'))SELECT u.username, u.account_status, u.created, u.last_login, u.profile, up.priv_type, COUNT(*) as privilege_count, LISTAGG(up.privilege, ', ') WITHIN GROUP (ORDER BY up.privilege) as privilegesFROM dba_users uLEFT JOIN user_privs up ON u.username = up.granteeWHERE u.username NOT IN ('SYS', 'SYSTEM', 'DBSNMP', 'XDB')GROUP BY u.username, u.account_status, u.created, u.last_login, u.profile, up.priv_typeORDER BY u.username, up.priv_type;
Data Access Audit Summary
Section titled “Data Access Audit Summary”-- Summary of data access by user and tableSELECT dbusername, object_schema, object_name, action_name, COUNT(*) as access_count, COUNT(DISTINCT TRUNC(event_timestamp)) as days_accessed, MIN(event_timestamp) as first_access, MAX(event_timestamp) as last_access, COUNT(DISTINCT sql_text) as unique_queriesFROM unified_audit_trailWHERE action_name IN ('SELECT', 'INSERT', 'UPDATE', 'DELETE') AND object_schema NOT IN ('SYS', 'SYSTEM') AND event_timestamp > SYSTIMESTAMP - INTERVAL '30' DAYGROUP BY dbusername, object_schema, object_name, action_nameORDER BY access_count DESC;
Security Compliance Checks
Section titled “Security Compliance Checks”Password Policy Compliance
Section titled “Password Policy Compliance”-- Check password policy settingsSELECT profile, resource_name, limitFROM dba_profilesWHERE resource_type = 'PASSWORD'ORDER BY profile, resource_name;
-- Users with non-expiring passwordsSELECT username, account_status, expiry_date, profile, created, password_change_dateFROM dba_usersWHERE account_status = 'OPEN' AND (expiry_date IS NULL OR expiry_date > SYSDATE + 365) AND username NOT IN ('SYS', 'SYSTEM')ORDER BY username;
-- Check for default passwordsSELECT username, account_statusFROM dba_users_with_defpwdWHERE username NOT IN ( SELECT username FROM dba_users WHERE account_status != 'OPEN');
Privilege Analysis
Section titled “Privilege Analysis”-- Users with excessive privilegesSELECT grantee, COUNT(*) as dangerous_privsFROM dba_sys_privsWHERE privilege IN ( 'ALTER SYSTEM', 'ALTER DATABASE', 'CREATE ANY TABLE', 'DROP ANY TABLE', 'SELECT ANY TABLE', 'UPDATE ANY TABLE', 'DELETE ANY TABLE', 'GRANT ANY PRIVILEGE', 'GRANT ANY ROLE', 'CREATE USER', 'DROP USER') AND grantee NOT IN ('SYS', 'SYSTEM', 'DBA')GROUP BY granteeORDER BY dangerous_privs DESC;
-- Analyze role hierarchiesWITH role_tree AS ( SELECT granted_role, grantee, admin_option, LEVEL as depth, SYS_CONNECT_BY_PATH(granted_role, ' -> ') as role_path FROM dba_role_privs START WITH granted_role IN ('DBA', 'RESOURCE', 'CONNECT') CONNECT BY PRIOR grantee = granted_role)SELECT * FROM role_treeWHERE grantee NOT IN ('SYS', 'SYSTEM')ORDER BY depth, granted_role, grantee;
Audit Management
Section titled “Audit Management”Audit Trail Maintenance
Section titled “Audit Trail Maintenance”-- Create procedure for audit trail archivalCREATE OR REPLACE PROCEDURE archive_audit_trail( p_days_to_keep IN NUMBER DEFAULT 90) IS v_archived_count NUMBER; v_archive_date DATE;BEGIN v_archive_date := SYSDATE - p_days_to_keep;
-- Archive to history table INSERT INTO audit_trail_archive SELECT * FROM unified_audit_trail WHERE event_timestamp < v_archive_date;
v_archived_count := SQL%ROWCOUNT;
-- Delete archived records DELETE FROM unified_audit_trail WHERE event_timestamp < v_archive_date;
COMMIT;
DBMS_OUTPUT.PUT_LINE('Archived ' || v_archived_count || ' audit records');
-- Update statistics DBMS_STATS.GATHER_TABLE_STATS( ownname => 'AUDSYS', tabname => 'AUD$UNIFIED' );
EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE;END;/
-- Schedule audit trail maintenanceBEGIN DBMS_SCHEDULER.CREATE_JOB( job_name => 'AUDIT_TRAIL_MAINTENANCE', job_type => 'PLSQL_BLOCK', job_action => 'BEGIN archive_audit_trail(90); END;', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=WEEKLY; BYDAY=SUN; BYHOUR=2', enabled => TRUE, comments => 'Weekly audit trail archival and cleanup' );END;/
Audit Performance Impact Analysis
Section titled “Audit Performance Impact Analysis”-- Monitor audit overheadSELECT name, valueFROM v$sysstatWHERE name IN ( 'audit records generated', 'audit file writes', 'audit file size', 'audit queue flush waits')ORDER BY name;
-- Check audit trail sizeSELECT segment_name, segment_type, ROUND(bytes/1024/1024, 2) as size_mb, tablespace_nameFROM dba_segmentsWHERE owner = 'AUDSYS'ORDER BY bytes DESC;
Custom Compliance Reports
Section titled “Custom Compliance Reports”SOX Compliance Report
Section titled “SOX Compliance Report”CREATE OR REPLACE PROCEDURE generate_sox_compliance_report( p_start_date IN DATE, p_end_date IN DATE) IS v_report CLOB; v_section VARCHAR2(32000);BEGIN v_report := 'SOX Compliance Report' || CHR(10) || '=====================' || CHR(10) || 'Period: ' || p_start_date || ' to ' || p_end_date || CHR(10) || CHR(10);
-- Section 1: User Access Changes v_section := 'User Access Changes:' || CHR(10); FOR rec IN ( SELECT event_timestamp, dbusername, action_name, target_user, sql_text FROM unified_audit_trail WHERE action_name IN ('CREATE USER', 'DROP USER', 'ALTER USER', 'GRANT', 'REVOKE') AND event_timestamp BETWEEN p_start_date AND p_end_date ORDER BY event_timestamp ) LOOP v_section := v_section || TO_CHAR(rec.event_timestamp, 'DD-MON-YY HH24:MI') || ' - ' || rec.dbusername || ' - ' || rec.action_name || ' - ' || NVL(rec.target_user, 'N/A') || CHR(10); END LOOP;
v_report := v_report || v_section || CHR(10);
-- Section 2: Data Modifications on Financial Tables v_section := 'Financial Data Modifications:' || CHR(10); FOR rec IN ( SELECT event_timestamp, dbusername, action_name, object_schema, object_name, return_code FROM unified_audit_trail WHERE action_name IN ('INSERT', 'UPDATE', 'DELETE') AND object_schema = 'FINANCE' AND event_timestamp BETWEEN p_start_date AND p_end_date ORDER BY event_timestamp ) LOOP v_section := v_section || TO_CHAR(rec.event_timestamp, 'DD-MON-YY HH24:MI') || ' - ' || rec.dbusername || ' - ' || rec.action_name || ' on ' || rec.object_schema || '.' || rec.object_name || CHR(10); END LOOP;
v_report := v_report || v_section;
-- Output or store report DBMS_OUTPUT.PUT_LINE(v_report);
-- Store in compliance_reports table INSERT INTO compliance_reports ( report_type, report_date, report_content, generated_by ) VALUES ( 'SOX_COMPLIANCE', SYSDATE, v_report, USER );
COMMIT;END;/
Real-time Security Monitoring
Section titled “Real-time Security Monitoring”-- Create view for security dashboardCREATE OR REPLACE VIEW v_security_dashboard ASSELECT 'Failed Logins (24h)' as metric, COUNT(*) as valueFROM unified_audit_trailWHERE action_name = 'LOGON' AND return_code != 0 AND event_timestamp > SYSTIMESTAMP - INTERVAL '24' HOUR
UNION ALL
SELECT 'Privilege Grants (7d)' as metric, COUNT(*) as valueFROM unified_audit_trailWHERE action_name IN ('GRANT', 'REVOKE') AND event_timestamp > SYSTIMESTAMP - INTERVAL '7' DAY
UNION ALL
SELECT 'Schema Changes (7d)' as metric, COUNT(*) as valueFROM unified_audit_trailWHERE action_name LIKE '%TABLE%' OR action_name LIKE '%INDEX%' AND event_timestamp > SYSTIMESTAMP - INTERVAL '7' DAY
UNION ALL
SELECT 'Sensitive Data Access (24h)' as metric, COUNT(*) as valueFROM unified_audit_trailWHERE object_schema IN ('HR', 'FINANCE', 'PAYROLL') AND action_name = 'SELECT' AND event_timestamp > SYSTIMESTAMP - INTERVAL '24' HOUR;
Best Practices
Section titled “Best Practices”- Policy Design: Create focused audit policies for specific compliance needs
- Performance: Monitor audit overhead and adjust policies accordingly
- Retention: Implement appropriate retention periods for audit data
- Analysis: Regularly review audit trails for anomalies
- Archival: Archive old audit data to maintain performance
- Security: Protect audit trails from unauthorized modification
- Automation: Automate compliance reporting and anomaly detection