Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Saradha.

Asked: August 19, 2002 - 12:27 pm UTC

Last updated: September 25, 2006 - 2:11 am UTC

Version: 8.1.7.4

Viewed 10K+ times! This question is

You Asked

Tom,

I would like to prevent a set of users logging into the
application whenever there is a need.

For example, while some batach jobs (or conversion programs) running on some tables, I would like to prevent set of users who access those
tables while allowing other users to logon.

All the application users logging into the database through the application connect to the database using the same SCHEMA (Schema name: BSARP)

But all the application user names are stored in a table with the region they belong to.

USERADMIN table.

appuser region
----------- -------
PETER NJ
TIGER NJ
..... ..
MILTON NY
CHRIS NY
.... NY

At a given time, I want to prevent users belong to a particular region logging into the application.

So I thought of having a AFTER LOGON trigger enabled to prevent the user and have the trigger disabled when we want to allow everybody in the system.

For example,
If I want to prevent all the users belonging to NY region.

CREATE OR REPLACE TRIGGER prevent_ny_users AFTER LOGON
ON SCHEMA
DECLARE
app_user VARCHAR2(30);
app_region useradmin.region%TYPE;
BEGIN
SELECT osuser INTO app_user FROM v$session
WHERE audsid = USERENV('sessionid');

SELECT region INTO app_region
FROM useradmin
WHERE userid = app_user;

IF ( app_region = 'NY' ) THEN
RAISE_APPLICATION_ERROR(-20001,'The system is not currently available for this region');
END IF;

END;
/

The above trigger is created successfully under BSARP schema but it is not working. It seems the RAISE_APPLICATION_ERROR is not working here.

I searched for this in your archives and I did find a similar one but
that example of trigger is on DATABASE level.

Can you please guide me on how to correct this or suggest me any other better approach to handle this situation.

The schema BSARP does not have DBA role and it has the privilege
for executing all the application stored programs and necessary privileges on application tables and views.

Thanks
Saradha

and Tom said...

You'll have to use a DATABASE level trigger -- the trigger will not prevent the owner from logging in (to avoid serious problems if the trigger is invalid or otherwise failing). It would work like this:


ops$tkyte@ORA817DEV.US.ORACLE.COM> drop user bsarp cascade;
User dropped.

ops$tkyte@ORA817DEV.US.ORACLE.COM> create user bsarp identified by x;
User created.

ops$tkyte@ORA817DEV.US.ORACLE.COM> grant connect, create table, unlimited tablespace to bsarp;
Grant succeeded.

ops$tkyte@ORA817DEV.US.ORACLE.COM> @connect bsarp/x

bsarp@ORA817DEV.US.ORACLE.COM> create table useradmin ( region varchar2(5), userid varchar(30) );
Table created.

bsarp@ORA817DEV.US.ORACLE.COM> insert into useradmin values ( 'NY', 'tkyte' );
1 row created.

bsarp@ORA817DEV.US.ORACLE.COM> grant select on useradmin to ops$tkyte;
Grant succeeded.

bsarp@ORA817DEV.US.ORACLE.COM> @connect /

ops$tkyte@ORA817DEV.US.ORACLE.COM> CREATE OR REPLACE TRIGGER prevent_ny_users
2 AFTER LOGON
3 ON database when (user='BSARP')

4 DECLARE
5 app_user VARCHAR2(30);
6 app_region useradmin.region%TYPE;
7 BEGIN
8 SELECT osuser INTO app_user FROM v$session
9 WHERE audsid = USERENV('sessionid');
10
11 SELECT region INTO app_region
12 FROM bsarp.useradmin
13 WHERE userid = app_user;
14
15 IF ( app_region = 'NY' ) THEN
16 RAISE_APPLICATION_ERROR(-20001,'The system is not currently available for this region');
17 END IF;
18 END;
19 /

Trigger created.

ops$tkyte@ORA817DEV.US.ORACLE.COM> disconnect
Disconnected from Oracle8i Enterprise Edition Release 8.1.7.4.0 - Production
With the Partitioning option
JServer Release 8.1.7.4.0 - Production
ops$tkyte@ORA817DEV.US.ORACLE.COM> connect bsarp/x
ERROR:
ORA-00604: error occurred at recursive SQL level 1
ORA-20001: The system is not currently available for this region
ORA-06512: at line 13


ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> @connect /
ops$tkyte@ORA817DEV.US.ORACLE.COM> set termout off
ops$tkyte@ORA817DEV.US.ORACLE.COM> REM GET afiedt.buf NOLIST
ops$tkyte@ORA817DEV.US.ORACLE.COM> set termout on
ops$tkyte@ORA817DEV.US.ORACLE.COM> drop trigger prevent_ny_users;

Trigger dropped.

Rating

  (30 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Saradha Bavanandam, August 20, 2002 - 11:06 am UTC

Tom,

Thank you very much for your response.

My DBA does not want to take this responsibility of creating
the trigger and droping the trigger as he has to be available all the time whenever we need this requirement and also does not want to grant the DBA role to anybody else.
I initially thought that CREATE ANY TRIGGER privilege will allow to create this trigger but it is not.

I do not know what I am left with now.

Is it possible for the DBA to grant only certain privileges to another schema to create and drop this DATABASE LEVEL trigger.

If not then I will have to think of some other mechanism to handle this requirement.

Thanks once again for your help.
Saradha

Tom Kyte
August 20, 2002 - 1:50 pm UTC

As bsarp, create another table

create table regions_to_block ( region varchar2(30) );

Then, in the trigger code:

declare
l_count number;
begin
select count(*) into l_count
from dual
where exists ( select NULL
from bsarp.useradmin
where userid = (select osuser
from v$session
where audsid = userenv('sessionid')
)
and region in ( select region
from bsarp.regions_to_block )
);

if (l_count = 1)
then
RAISE_APPLICATION_ERROR(-20001,
'The system is not currently available for this region');
end if;
end;


Now it is 100% table driven. bsarp inserts a row -- no logging in for that region. bsarp deletes a row and logging in just happens.

Saradha Bavanandam, August 20, 2002 - 2:36 pm UTC

Tom,

I did more research and read more documentation and this is
what I found out as a posssible solution.

I have modified the following trigger with 
AFTER LOGON BSARP.SCHEMA and compiled the trigger from
another schema who has CREATE ANY TRIGGER privilege but
does not have DBA role and it seems to be working.

I have logged on to the database using LADEV userid.
$sqlplus LADEV/LADEV

This schema has the following privileges.
SQL> SELECT * FROM SESSION_PRIVS;
     create session
     alter session
     create table
     select any table
     create view
     create sequence
     create procedure
     create trigger
     CREATE ANY TRIGGER
     execute any procedure
     administer resource manager

And I created the following trigger

SQL> CREATE OR REPLACE TRIGGER prevent_ny_users  
2  AFTER LOGON
3  ON BSARP.SCHEMA
4  DECLARE  
5     app_user   VARCHAR2(30);
6     app_region useradmin.region%TYPE;  
7  BEGIN
8     SELECT osuser INTO app_user FROM v$session
9     WHERE audsid = USERENV('sessionid'); 
10  
11     SELECT region INTO app_region 
12     FROM   bsarp.useradmin
13     WHERE  userid = app_user; 
14   
15     IF ( app_region = 'NY' ) THEN
16         RAISE_APPLICATION_ERROR(-20001,'The system is not currently 
available for this region'); 
17     END IF; 
18  END; 
19  /

Trigger created.

SQL> EXIT

Now I try to logon to the BSARP schema and PETER is the operating system user.

$whoami
PETER

$sqlplus BSARP/BSARP

SQL*Plus: Release 8.1.7.0.0 - Production on Tue Aug 20 13:49:32 2002

(c) Copyright 2000 Oracle Corporation.  All rights reserved.

ERROR:
ORA-00604: error occurred at recursive SQL level 1
ORA-20001: The system is not currently available for this region
ORA-06512: at line 13


So with this, the trigger does not have to be a DATABASE LEVEL trigger.

May I please know why you may not have suggested this. Is there any risk or serious problem involved in this method.

Thanks for your advise again.
Saradha 

Tom Kyte
August 20, 2002 - 2:48 pm UTC

Suggest you use the table driven approach I recommended above along with a STATIC, one time trigger that is always there.

1) it is easier
2) it is more understandable
3) Anytime you need "ANY" type privs, you want to think really hard.

For example, given CREATE SESSION and EXECUTE ANY PROCEDURE I could take over your databaes easily (just those two)

Give me CREATE SESSION and CREATE ANY TRIGGER and I could grant myself EXECUTE ANY PROCEDURE without you know it and take over....

These are very powerful privs you are playing with. Go with the solution that requires NO new users and NO overly powerful users.

Security issue...

Sven Bleckwedel, September 13, 2002 - 11:04 am UTC

Tom,

I had some doubts about this issue, because I´m looking in these scenarios right now. Can you do some examples, about this fact, as you described ?

"
For example, given CREATE SESSION and EXECUTE ANY PROCEDURE I could take over
your databaes easily (just those two)

Give me CREATE SESSION and CREATE ANY TRIGGER and I could grant myself EXECUTE
ANY PROCEDURE without you know it and take over....

These are very powerful privs you are playing with. Go with the solution that
requires NO new users and NO overly powerful users.
"

As you described, some of these privileges are part of the DEFAULT roles (CREATE SESSION in CONNECT and CREATE TRIGGER in RESOURCE). What is the essential difference for CREATE TRIGGER and CREATE ANY TRIGGER, in this point-of-view ?...

Rgds,
Sven


Tom Kyte
September 14, 2002 - 2:05 pm UTC

rather not describe exactly how.

Just be wary of anyone with any of the "ANY" privs.

Natural side effect of having this very POWERFUL privilege

Sven Bleckwedel, September 18, 2002 - 4:52 pm UTC

Tom,

Ok. But, to me is natural to know what I have to do, when the possibility exists:

>... if you give me:
>o create session
>o execute any procedure
>I can take over your database and get ANY priv I want. It
>would take about 30 seconds for me to have DBA and
>anything else I wanted.
>----------------------------------------------------------
>alter user -- hmm, with that I rule the WORLD ;) I can
>become SYS or anyone I want to....
>-----------------------------------------------------------
>I'd rather not say. The knowledge that it is so should be
>more then enough hopefully to make people go out there and
>reconsider how they grant privs and what privs they grant.
>Think about it -- you can run ANY procedure in the
>database, any SYS owned procedures, whatever you want...
>----------------------------------------------------------
>The knowledge that the ability exists is more then enough
>knowledge.
>This really isn't a hole, it is a natural side effect of
>having this very POWERFUL privilege.
>-----------------------------------------------------------
>Now, give me create session, execute any procedure, xxxxx
>xxx xxxxxxxxx -- and I'm back in business ;)

Of course, "xxxxx xxx xxxxxxxxx" can be "grant any privilege" ? Where can i read more about these privs ?

Rgds,
Sven


Tom Kyte
September 18, 2002 - 6:54 pm UTC

The SQL reference manual.
The ADMIN guide.

Not a spoiler, but....

Mark J. Bobak, September 19, 2002 - 5:21 am UTC

Tom,

I'm surprised you didn't mention that Oracle (at least 8iR3
and 9iR1) come with at least one default user/password
combination that has create session and execute any procedure.

Yep, they put it in the database for you, by default.

I'm willing to bet a huge majority of databases have this
security hole just sitting there.

So, if you never worried about those default users Oracle
creates when a new database is installed, you may want
to take a second look at them.....;-)

-Mark

Sagi, September 19, 2002 - 6:51 am UTC

Thanx Tom.

One more good example.

Mark. I did not get what u were talking about. Were you referring to SYS & SYSTEM users with their default passwords?



Tom Kyte
September 19, 2002 - 8:05 am UTC

He means we should run:

select grantee from dba_sys_privs where privilege = 'EXECUTE ANY PROCEDURE';

and make sure the accounts that pop up don't have their default passwords still there (eg: you've changed them). if they do, watch out.

RE: Not a spoiler...

Mark A. Williams, September 19, 2002 - 8:24 am UTC

Mark:

Very valid point!

Strong argument for:

1) not using a "default" database...

2) never installing "sample" schemas into prod. databases...

3) knowing what you are doing...

4) checking up on things...

5) reading this document: </code> http://otn.oracle.com/docs/products/oracle9i/doc_library/release2/network.920/a96582/toc.htm <code>

I regularly perform security audits on my databases and wonder why security seems to take a back seat. Oh so many people want to figure out how to turn of logging of operations, but are numb to the fact that their database could be "wide-open"...

- Mark (from Indy)

BTW, I wonder if it is possible to create a logon Winnie the Pooh? (See title from Original Poster - very bad joke).

Tom Kyte
September 19, 2002 - 8:45 am UTC

in 9iR2 -- you should be glad to hear, the default accounts are all locked and sys/system won't have change_on_install and manager and sysdba/sys/sysoper actions can be audited (and dba's can grant on others objects and the create database command supports passwords for sys/system as well)

Thanks Tom!

Mark A. Williams, September 19, 2002 - 8:50 am UTC

Tom:

Thanks for the feedback! There are many benefits to 9iR2 from my perspective. I have 2 9iR1 databases, but most new/upgrades are going straight to R2! I was glad to see the 07_dictionary_accessibility default to false beginning with R1 as well... I have a long list of improvements that I appreciate.

One improvement that I really like is system managed segment space (ie, segment management auto). However, I recently read a post from Howard Rogers on c.d.o.s wherein he felt that the parameter was only useful for a RAC config. I use it in non-RAC servers with no problems... he didn't really give any reasoning behind his assertion IIRC...

BTW, why does AskTom not set a cookie on my machine with my name/location/etc... like it used to?

Oh, well, don't want to start a new thread here!

Thanks again,

- Mark W.

zl, September 19, 2002 - 10:36 pm UTC

you said "given CREATE SESSION and EXECUTE ANY PROCEDURE I could take over your databaes easily (just those two)".
how to do that?
thanks.

To zl from China

Mark A. Williams, September 20, 2002 - 9:44 am UTC

Visit this thread here for reasons why this is a potential issue (and why the way to abuse it isn't "published").

</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:862779019442 <code>

HTH,

Mark W.

people are going to figure this out themselves

A reader, July 02, 2003 - 3:44 pm UTC

All these mystifying and obscuring attempts only serve one purpose (not intended by our kind hearted folks): you created more hype than anything regarding this perceived "security issue".

Here is an easy one:

Connected to:
Oracle8i Enterprise Edition Release 8.1.7.4.0 - Production
With the Partitioning option
JServer Release 8.1.7.4.0 - Production

12:39:26 SQL> sho user
USER is "SYSTEM"
12:39:28 SQL> sho parameter o7

NAME                     TYPE          VALUE
------------------------------------ -------------------- ------------------------------
O7_DICTIONARY_ACCESSIBILITY         boolean          TRUE
12:39:33 SQL> create user lowlife identified by highlife default tablespace users temporary tablespace temp;

User created.

Elapsed: 00:00:00.00
12:40:36 SQL> grant create session, execute any procedure to lowlife;

Grant succeeded.

Elapsed: 00:00:00.00
12:40:48 SQL> conn lowlife/highlife
Connected.
12:40:59 SQL> select * from session_privs;

PRIVILEGE
----------------------------------------
CREATE SESSION
EXECUTE ANY PROCEDURE

2 rows selected.

Elapsed: 00:00:00.00
12:41:05 SQL> exec dbms_repcat_admin.grant_admin_any_schema('lowlife')

PL/SQL procedure successfully completed.

Elapsed: 00:00:01.01
12:41:30 SQL> select * from session_privs;

PRIVILEGE
----------------------------------------
CREATE SESSION
ALTER SESSION
UNLIMITED TABLESPACE
CREATE ANY TABLE
ALTER ANY TABLE
DROP ANY TABLE
COMMENT ANY TABLE
SELECT ANY TABLE
INSERT ANY TABLE
UPDATE ANY TABLE
DELETE ANY TABLE
CREATE ANY CLUSTER
ALTER ANY CLUSTER
DROP ANY CLUSTER
CREATE ANY INDEX
ALTER ANY INDEX
DROP ANY INDEX
CREATE ANY SYNONYM
DROP ANY SYNONYM
CREATE PUBLIC SYNONYM
DROP PUBLIC SYNONYM
CREATE ANY VIEW
DROP ANY VIEW
CREATE ANY SEQUENCE
ALTER ANY SEQUENCE
DROP ANY SEQUENCE
CREATE DATABASE LINK
CREATE ANY PROCEDURE
ALTER ANY PROCEDURE
DROP ANY PROCEDURE
EXECUTE ANY PROCEDURE
CREATE ANY TRIGGER
ALTER ANY TRIGGER
DROP ANY TRIGGER
CREATE ANY SNAPSHOT
ALTER ANY SNAPSHOT
DROP ANY SNAPSHOT

37 rows selected.

Elapsed: 00:00:00.00
12:41:36 SQL> 
     

 

Tom Kyte
July 02, 2003 - 4:10 pm UTC

so why the air quotes

...
perceived "security issue".
.....


you just proved the entire point. If I created "hype" -- excellent, hope I did.

It is not a perceived issue, you've just show exactly how "real" the issue is.

full disclosure

A reader, July 02, 2003 - 6:15 pm UTC

I mean, instead of saying (something like) "I'd rather not describe exactly how it's done", how about simply disclose how it can be done? The reader, who provided a link to the "reasons why this is a potential issue (and why the
way to abuse it isn't "published")", mystified the issue even further, which only provokes people's curiosity. My opinion: don't obscure, just fully disclose. Overall that's better for the public.


Tom Kyte
July 03, 2003 - 8:44 am UTC

no, you showed but one way. there are many others.

Now, maybe will have a bunch of people that say "ok, i get rid of that package and I'm safe"...

all you need to know is "if someone has these, they have the ability to do anything they want"

which public?

Kamal Kishore, July 02, 2003 - 10:25 pm UTC

<quote ID="Previous Poster">
My opinion: don't obscure, just fully
disclose. Overall that's better for the public.
</quote>

Well, which "public" are you serving here by this discloser?
The ones who are trying to protect the assets (here their database) and get something useful done or the ones who have nothing else useful to do other than to be "on the lookout" for such issues and are always looking for (or many times create one) the step-by-step guide (which you provided as a generous gift to them)?

Your example served the needs of the second class of "public" wereas we are trying to serve the first class of "public".

Which side are you on, really?


There is only ONE public

A reader, July 02, 2003 - 11:07 pm UTC

It's very funny that some people always have the constant craving for taking sides. You might as well suggest software companies deny the existence of any security holes, because the mere mentioning of some particular security issues is enough to serve those "second class" people that you referred to.

In this case, the simple disclosure made by Tom that "create session and execute any procedure are two privileges that are enough for one to take over the whole database" actually is quite enough for a knowledgeable person to find the way in easily. Knowing how it is done is good for the public to understand the severity of the issue and come up with ways to prevent it (turn o7_dictionary_accessibility = false), or monitor it (audit the exec of any dbms_* procs), therefore find the culprit. Think about it, if you don't even know how people get in, how are you suppose to know which doors to secure and which pathways to monitor? You are a big joker. Hope you don't work for any security firm (this is joke ;-).



How about...

Kamal Kishore, July 03, 2003 - 9:15 am UTC

I don't think I can be as big a joke(er) than you have presented yourself. I'll leave that spot for you.

How about this:
I, don't work for security firm.
You, don't work at all.

That would be best serving the industry.


Yet another great discussion

Arun Mathur, July 16, 2003 - 4:50 pm UTC

Tom,

The person who originally posted the question mentioned that the RAISE_APPLICATION_ERROR didn't work when the trigger was performed on the schema. Can you go over why it didn't work?

All the best,
Arun

Tom Kyte
July 16, 2003 - 4:56 pm UTC

it is in the 1st paragraph of my response.

Prompt for Application Userid and Password

A reader, September 02, 2003 - 11:27 pm UTC

Is there any wy i can prompt the user to enter the userid and password (Which is application userid and pwd after the user has logged in) from sqlplus

Tom Kyte
September 03, 2003 - 6:55 am UTC

they would have to use

sqlplus /nolog


and all you need do is put "connect" in a script


[tkyte@tkyte-pc-isdn tkyte]$ sqlplus /nolog

SQL*Plus: Release 9.2.0.3.0 - Production on Wed Sep 3 06:57:13 2003

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

idle> connect
Enter user-name: scott
Enter password:
Connected.
idle>


How to use a Database Startup Trigger

TH, December 28, 2003 - 9:15 am UTC

Dear Tom,
I want to update a certain table in a particular schema when the Oracle starts. Which is that trigger? Waiting for your reply,

TH, BAH

Tom Kyte
December 28, 2003 - 11:28 am UTC

</code> http://docs.oracle.com/docs/cd/B10501_01/appdev.920/a96590/adg14evt.htm#998000 <code>

documents all of the system events, including the "after startup" trigger.

Riaz Shahid, December 29, 2003 - 7:34 am UTC

Tom !

Regarding to the original question, doesn't the
Alter System enable restricted session
will be enough ? (by giving retricted session grant to only the users which are needed to be given permission)

Tom Kyte
December 29, 2003 - 10:38 am UTC

Nope:

"All the application users logging into the database through the application
connect to the database using the same SCHEMA (Schema name: BSARP)"

they all use the same userid in the database.

SEcurity needs more attention !!

Orlando Reyes, February 03, 2005 - 12:05 pm UTC

Tom,

I already knew about this issue, but in some databases where I found the situation I tried to prove it and I have not have any luck. Here is my example:

After connection with user WEBAPP.

test> select * from session_privs;

PRIVILEGE
----------------------------------------
CREATE SESSION
UNLIMITED TABLESPACE
EXECUTE ANY PROCEDURE

but when executing dbms_repcat_admin.grant_admin_any_schema('WEBAPP');

test> exec dbms_repcat_admin.grant_admin_any_schema('WEBAPP');
BEGIN dbms_repcat_admin.grant_admin_any_schema('WEBAPP'); END;

*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'DBMS_REPCAT_ADMIN' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

I also tried using sys.dbms_repcat_admin.grant_admin_any_schema, but got the same error, in fact the describe does not work either.

test> desc sys.dbms_repcat_admin
ERROR:
ORA-04043: object sys.dbms_repcat_admin does not exist

I did verified the package exists and is valid.

Is there something else preventing the user from seeing/running the package even though it has 'EXECUTE ANY PROCEDURE'?.

In a way I am glad it works this way, but I would like to know why or if I am missing something.

As usual, thanks for the great stuff.

Orlando


Tom Kyte
February 03, 2005 - 2:43 pm UTC

sys owned packages are special.

ANY privs are not sufficient for SYS stuff (for good reason)

That makes a lot of sence.

Orlando Reyes, February 03, 2005 - 3:18 pm UTC

So Tom,

How is it that people claim that this works?

test> exec dbms_repcat_admin.grant_admin_any_schema('WEBAPP');

Is it because the package gets created under some other schema? Like running the ORACLE_HOME/rdbms/admin/catrep.sql script under system for example? But if that was the case, how could the package have the right privileges anyway?

Thanks again,

Orlando



Tom Kyte
February 04, 2005 - 1:23 am UTC

because they were granted execute on that package directly perhaps.



That makes a lot of sence.

Orlando Reyes, February 03, 2005 - 3:19 pm UTC

So Tom,

How is it that people claim that this works?

test> exec dbms_repcat_admin.grant_admin_any_schema('WEBAPP');

Is it because the package gets created under some other schema? Like running the ORACLE_HOME/rdbms/admin/catrep.sql script under system for example? But if that was the case, how could the package have the right privileges anyway?

Thanks again,

Orlando



Create Any Trigger - also potential security issue ?

Tim, February 18, 2005 - 6:13 pm UTC

We have triggers created in a particular schema, MainApp. It would be most convenient to be able to see these from another schema DevPlay. (For application development purposes.) However, I have read that the only way these triggers can be seen is to grant the CREATE ANY TRIGGER to DEV - which seems like it would fall under (or related to) the security risk you are mentioning.

So, my question: Am I incorrect in that granting this would not be a security risk? And/or is there another way to allow the triggers to be conveniently VIEWed (but not changed) without this particular grant?
Thanks.

Tom Kyte
February 18, 2005 - 6:53 pm UTC

that would be a huge problem.

that is like having "drop any trigger" (as you can create or replace any trigger)

i could put triggers on tables to snoop data (i'd have :new and :old to peek at).  Well, heck, why bother with that slow channel of peeking, when I could just:

ops$tkyte@ORA9IR2> drop user a cascade;
 
User dropped.
 
ops$tkyte@ORA9IR2> create user a identified by a;
 
User created.
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> grant create session, create any trigger to a;
 
Grant succeeded.
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> create table t ( x int );
 
Table created.
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> @connect a/a
ops$tkyte@ORA9IR2> set termout off
a@ORA9IR2> set termout on
a@ORA9IR2>
a@ORA9IR2> create trigger ops$tkyte.give_me_more before insert on ops$tkyte.t
  2  declare
  3          pragma autonomous_transaction;
  4  begin
  5          execute immediate 'grant select on ops$tkyte.t to a';
  6  end;
  7  /
 
Trigger created.
 
a@ORA9IR2>
a@ORA9IR2> select * from ops$tkyte.t;
select * from ops$tkyte.t
                        *
ERROR at line 1:
ORA-00942: table or view does not exist
 
 
a@ORA9IR2>
a@ORA9IR2> @connect /
a@ORA9IR2> set termout off
ops$tkyte@ORA9IR2> set termout on
ops$tkyte@ORA9IR2> insert into t values ( 1 );
 
1 row created.
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> @connect a/a
ops$tkyte@ORA9IR2> set termout off
a@ORA9IR2> set termout on
a@ORA9IR2> select * from ops$tkyte.t;
 
         X
----------
         1


<b>beware of "any" privs</b>



You would want to use a stored procedure in that schema that would accept trigger text (and validate that it was safe somehow!) and have it do the create trigger.  You would grant execute on that trigger to whomever needed it. 

Create Any Trigger - also potential security issue ?

Tim, February 19, 2005 - 9:07 am UTC

Tom, thanks for the response. So, we will not use the "create any trigger". But, then how can another user VIEW the trigger from the schema where the trigger exists? For example, our developers are not allowed to create triggers in the production schema (or anywhere in the production 9iR2 database) for both QA & security reasons. (Developers have free run in their own development 9iR2 database.)

But, we would like to let developers be able to VIEW the production triggers such that they can compare production to development so as to ensure that what is *supposed* to be in production - really is.

So, developers have a production username with very few grants - basically grants same as a regular user. This means that when developers log in to their production username and try to VIEW the triggers from the production schema which owns the trigger - the developer can not see the trigger. (But tables, views, sequences, procedures are all visible.)

The ALL_TRIGGERS table returns zero rows for the developer - and documentation says that the only way to see information in here is to grant the CREATE ANY TRIGGER - which you clearly said should never be done in production.

So - any thoughts on how our developers can see the production triggers?

BTW - I did not understand in your last response when you said.. "You would grant execute on that trigger..."

Again - many thanks.



Tom Kyte
February 19, 2005 - 9:42 am UTC

have someone with access to dba_triggers create a view of dba_triggers that selects out just the production triggers and grant select on this new view to whomever needs it.

should have said "grant execute on that procedure (that creates the trigger)..."

On Startup

CLG, March 30, 2005 - 1:43 pm UTC

I have an Oracel 8.1.7.4.17 database and an 9.2.0.6 database.
Both have the same schema.


Why do I get this in the 9i database


Error in executing triggers on database startup
*** 2005-03-29 13:24:00.593
ksedmp: internal or fatal error
ORA-00604: error occurred at recursive SQL level 1
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "SAMS.ME_LIB", line 1233
ORA-06512: at line 2


but upon searching the udump and bdump folders on the 8i databases I
dont see this error?


I know that I need to remove the commit that is obvious but am I not
seeing this on my 8i databases?




Tom Kyte
March 30, 2005 - 2:05 pm UTC

a 1,233 line trigger, wow.

Looks like they want that to be an autonomous transaction in 9i

create or replace trigger startup_trigger
after startup on database
declare
pragma autonomous_transaction;
begin
commit;
end;
/


Thanks Problem Solved

CLG, March 30, 2005 - 3:18 pm UTC

By the way, that is not a 1,233 line trigger.

That is a package body. The trigger was calling a procedure in the package.

made the change you suggested and it works now.

Just a guess or you saw this before?

Tom Kyte
March 30, 2005 - 3:35 pm UTC

I tested it :)


"The Create Any" privs

Satya, April 25, 2006 - 11:23 am UTC

Oracle 9.2.0.6
Tom,
We have a setup where developers need to create triggers on
a few tables that are owned by a privileged account.
We were discussing different options to how we can help them do this without compromising the security.
One option is "Create Any trigger" be given to this developer account..so it can do what it needs to do..but that seems to be a no no..
other is creating a definer rights procedure (owned by a privileged account) that accepts the trigger text..and then tries to compile it..and returns errors if any..
What about then for packages and stuff..those can be big..
I guess the parameter then can be a clob...
Are there other solutions for this?

Thanks


Tom Kyte
April 25, 2006 - 2:19 pm UTC

it would be a "no no"

a trigger could be ONE LINE LONG - a simple call to an existing package.

It doesn't need to be very big at all - in fact, they should be small. I like the procedure idea - with a varchar2 input - upto 32k in size. A trigger bigger than that shouldn't exist.

How to stay away from any privs

Satya, April 25, 2006 - 2:35 pm UTC

Next book you write..have a chapter in it..with a heading
"How to say No to Any"..
and have these work arounds listed in it...
:)

Using an "after logon on database" trigger to set app contexts for multiple schema lifecycles

ht, September 22, 2006 - 8:08 pm UTC

Hi Tom,
I would like to add a test env to my dev env that currently exists on a single database.

I am using a logon trigger to set my app context to enforce fgac in my dev env.

Is it possible to modify my trigger or package to allow a single user the ability to also access a newly-created test env on the same database?

For example:

create or replace trigger logon_trigger
after logon on database
begin
schemadev1.pkg1.set_context;
/*
schematest1.pkg1.set_context;
*/
end;

I'm trying to figure out a way (besides creating another db) to have the logon trigger allow user1 to access both schemadev1 and schematest1 while setting different application context values (i.e. user1 has "admin" privs while in schemadev1 and "nonadmin" privs while in schematest1).

Thank you in advance,
ht

Tom Kyte
September 24, 2006 - 1:29 pm UTC

sorry, didn't follow what the real requirement was here.... the for example shows a valid trigger as it is, so it really didn't help clarify it :)

Creating multiple application contexts on the same database.

ht, September 24, 2006 - 4:03 pm UTC

Tom,
Sorry for not being clearer.

How can I create application contexts depending on the schema one is attaching too using a database's "on logon trigger"?

dev1.pkg1.set_app_context_dev
... dbms_session.set_context('my_ctx','role','admin'); ...


and

test1.pkg1.set_app_context_test
... dbms_session.set_context('my_ctx','role','guest'); ...

Since both dev and test have identical code, I'm trying to figure out how to stick to 1 database while allowing a user test/dev privs.

Tom Kyte
September 25, 2006 - 2:11 am UTC

One is not really "attaching to a schema" here - one is running a package owned by the schema "dev1" and one is then running a package owned by "test1"

I suppose this would be my recommendation - that you let the logon trigger do the "default" action and have the developer just know to call a function that sets the context appropriate to be set up for the "test1" run.

More to Explore

VLDB

If you are new to partitioning, check out Connor McDonald's introduction series here.

VLDB

Documentation set on VLDB and Partitioning.