Oracle DBMS_PRIVILEGE_CAPTURE: Introduction to Privilege Analysis

English

To operate Oracle Database securely, it is important to grant users only the minimum required privileges. Leaving unnecessary privileges can increase security risks, such as potential misuse in external attacks or accidental modification of critical data. An effective solution for this is DBMS_PRIVILEGE_CAPTURE. This feature records which privileges were actually used, making it possible to distinguish between required and unnecessary ones.
This article provides an overview of the feature, detailed usage instructions, common troubleshooting points, and operational notes.


Step Overview (Quick Procedure)

The basic flow when using DBMS_PRIVILEGE_CAPTURE is as follows. Beginners should first grasp this outline before diving into details.

  1. Grant the CAPTURE_ADMIN privilege to an administrative user.
  2. Create a capture policy using DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTURE.
  3. Start recording with ...ENABLE_CAPTURE, have the target user perform operations, then stop with ...DISABLE_CAPTURE.
  4. Run ...GENERATE_RESULT to finalize the result and check usage through dictionary views.
  5. Revoke privileges determined to be unnecessary in stages. Always keep backups so you can re-grant them if needed.

What Is DBMS_PRIVILEGE_CAPTURE?

DBMS_PRIVILEGE_CAPTURE is a security feature provided by Oracle Database. It records which privileges granted to users or roles were actually used and which were not. This enables privilege minimization (least privilege) based on real operational data.

For example: “We granted SELECT to this user, but are they also using INSERT or UPDATE?” With DBMS_PRIVILEGE_CAPTURE, such questions can be answered with evidence. Based on the results, you can safely clean up privileges by revoking those not in use.

Types of Captures

DBMS_PRIVILEGE_CAPTURE offers multiple capture modes. Use them depending on your needs.

TypeTargetUse Case
G_DATABASEEntire database (excluding SYS)Inventory of privileges in use across the database
G_ROLESessions where a specified role is enabledVerify whether application-specific roles are being used
G_CONTEXTSessions matching a given conditionNarrow down to a specific user or module
G_ROLE_AND_CONTEXTSessions meeting both role and conditionTargeted investigation of specific production applications

The condition for G_CONTEXT must be defined using SYS_CONTEXT. Example: SYS_CONTEXT('USERENV','SESSION_USER')='APP_USER'.


Prerequisites

Before using DBMS_PRIVILEGE_CAPTURE, ensure the following:

  • Target version: Oracle Database 19c (non-CDB configuration)
  • OS: Linux
  • Required privilege: An administrative user with CAPTURE_ADMIN
  • Limit: At most two policies can be enabled at the same time
  • Note: The SYS user is excluded (its activity is not recorded)

If these conditions are not met, prepare your environment in advance.


Usage and Example

The following section demonstrates the actual steps. We create sample users, grant roles, and capture their privilege usage.

0. Preparing Test Users and Objects

Create sample users and a table to build an environment where privilege usage can be verified later.

-- As DBA
CREATE USER app_owner IDENTIFIED BY "AppOwner#1" QUOTA UNLIMITED ON users;
GRANT CREATE SESSION, CREATE TABLE TO app_owner;

CREATE USER app_user IDENTIFIED BY "AppUser#1";
GRANT CREATE SESSION TO app_user;

CREATE ROLE r_app_read;

-- As app_owner, create a sample table
CONN app_owner/"AppOwner#1"
CREATE TABLE emp (
  empno NUMBER PRIMARY KEY,
  ename VARCHAR2(30)
);
INSERT INTO emp VALUES (7369, 'SMITH');
COMMIT;

-- Return to DBA and grant privileges to the role
CONN / AS SYSDBA
GRANT SELECT ON app_owner.emp TO r_app_read;
GRANT r_app_read TO app_user;

At this point, app_user does not have direct privileges but can access the emp table through the role.

1. Creating an Administrative User for Capture

CREATE USER secadmin IDENTIFIED BY "SecAdmin#1";
GRANT CREATE SESSION TO secadmin;
GRANT CAPTURE_ADMIN TO secadmin;

The secadmin user manages capture policies, enables/disables them, and checks results.

2. Creating a Capture Policy

Here, we limit the scope to a specific user (APP_USER).

CONN secadmin/"SecAdmin#1"
BEGIN
  DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTURE(
    name      => 'PA_APPUSER',
    type      => DBMS_PRIVILEGE_CAPTURE.G_CONTEXT,
    condition => 'SYS_CONTEXT(''USERENV'',''SESSION_USER'') = ''APP_USER'''
  );
END;
/

3. Starting Capture and Performing Operations

BEGIN
  DBMS_PRIVILEGE_CAPTURE.ENABLE_CAPTURE(name => 'PA_APPUSER');
END;
/

-- Operate as app_user
CONN app_user/"AppUser#1"
SELECT * FROM app_owner.emp WHERE empno = 7369;

-- Stop capture
CONN secadmin/"SecAdmin#1"
BEGIN
  DBMS_PRIVILEGE_CAPTURE.DISABLE_CAPTURE(name => 'PA_APPUSER');
END;
/

4. Checking Results

BEGIN
  DBMS_PRIVILEGE_CAPTURE.GENERATE_RESULT(name => 'PA_APPUSER');
END;
/

-- Privileges that were used
SELECT username, used_role, obj_priv, object_name
FROM   dba_used_objprivs
WHERE  capture = 'PA_APPUSER';

-- Privileges that were unused
SELECT username, rolename, obj_priv, object_name
FROM   dba_unused_objprivs
WHERE  capture = 'PA_APPUSER';

If entries appear in dba_used_objprivs, it means those privileges were actually exercised. If they appear in dba_unused_objprivs, those privileges were not used during the capture period.

Command execution example

SQL> set lin 1000 pages 1000
SQL> col username for a20
SQL> col used_role for a20
SQL> col obj_priv for a20
SQL> col object_name for a30
SQL> SELECT username, used_role, obj_priv, object_name
2 FROM dba_used_objprivs
3 WHERE capture = 'PA_APPUSER';

USERNAME USED_ROLE OBJ_PRIV OBJECT_NAME
-------------------- -------------------- -------------------- ------------------------------
APP_USER PUBLIC EXECUTE DBMS_APPLICATION_INFO
APP_USER R_APP_READ SELECT EMP
APP_USER PUBLIC SELECT DUAL

SQL> SELECT username, rolename, obj_priv, object_name
2 FROM dba_unused_objprivs
3 WHERE capture = 'PA_APPUSER';

no rows selected

5. Dropping the Policy (Cleanup)

After the investigation, drop the policy to remove unnecessary data.

BEGIN
  DBMS_PRIVILEGE_CAPTURE.DROP_CAPTURE(name => 'PA_APPUSER');
END;
/

Troubleshooting

Common errors encountered when using DBMS_PRIVILEGE_CAPTURE are summarized below.

ErrorCauseCheck / Resolution
ORA-01031CAPTURE_ADMIN not grantedRun GRANT CAPTURE_ADMIN TO <username>;
ORA-47934Already two policies enabledCheck with SELECT name, enabled FROM dba_priv_captures; and disable unnecessary ones
Empty resultNo operations performed / condition too strictRelax condition or try again using G_DATABASE
No SYS resultsBy designSYS user is excluded and must be considered during design

Notes

  • SYSAUX management: Results are stored in the SYSAUX tablespace. If left unattended, it may grow significantly. Clean up periodically.
  • Interpretation of unused privileges: Even if privileges appear unused during the capture period, they may be needed for monthly or annual jobs. Ensure the observation window is long enough.
  • Revocation risks: Before revoking privileges, always take backups. If problems arise, re-grant immediately.
  • Operational considerations: In production, it is more efficient to enable/disable captures during specific events or releases rather than leaving them always on.

FAQ

Q1. How do I check only a specific user?
→ Use G_CONTEXT with the condition SYS_CONTEXT('USERENV','SESSION_USER')='APP_USER'.

Q2. Which dictionary views should I check?
→ Start with DBA_USED_OBJPRIVS and DBA_UNUSED_OBJPRIVS. If necessary, use “_PATH” views to trace grant paths.

Q3. Can I leave capture always enabled?
→ Technically possible, but not recommended as it increases SYSAUX usage. Run it for limited periods instead.

Q4. Are there differences in newer versions (e.g., 23ai)?
→ The core functionality is the same, but documentation structure and view specifications may change. Always check version-specific manuals.

Q5. Can privilege usage through roles be identified?
→ Yes. The USED_ROLE column shows whether privileges were exercised via a role, distinguishing direct grants from role-based usage.


Summary

  • DBMS_PRIVILEGE_CAPTURE enables you to clearly identify used and unused privileges.
  • To narrow down to specific users or modules, use G_CONTEXT.
  • At most two policies can be enabled at the same time.
  • SYS user is excluded and must be considered in design.
  • Ensure long enough observation periods, safely revoke unnecessary privileges, and manage SYSAUX regularly.

This article targets Oracle Database 19c. Screens and specifications may differ in other versions.


[reference]
Performing Privilege Analysis to Identify Privilege Use


[Read this article in Japanese]
Oracle DBMS_PRIVILEGE_CAPTUREによる権限チェック入門 | オラクルマスターを取得しよう

コメント

Copied title and URL