1. Trang chủ
  2. » Công Nghệ Thông Tin

Applied Oracle Security: Developing Secure Database and Middleware Environments- P52 pps

10 213 2
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 288,77 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The classic VPD use case is to set one or more session context variables when an end user logs into an application, and then use those context variables in a VPD policy that determines t

Trang 1

Virtual Private Database

VPD is one of the best ways to push data security down to the lowest possible level It’s easy

to envision scenarios in which all the data security was built into the application layer When another technology is introduced that needs to access the same data, the semantics of the security policy has to be replicated to the new technology Obviously, this is difficult to maintain, prone

to errors, and easy to subvert, because all a nefarious individual has to do to access the data is connect directly to the database, effectively bypassing the security

VPD is a critically important solution to protect the data at the source The classic VPD use case is to set one or more session context variables when an end user logs into an application, and then use those context variables in a VPD policy that determines the rows to which a user has access This is a fairly straightforward task in client-server environments, where the database session of an end user persists as long as the user is logged into the application As discussed in Chapter 11, APEX database sessions persist only as long as it takes to process a page request, which is typically less than a second This is yet another area where the difference between nonpersistent and persistent sessions causes a lot of confusion for developers

Fortunately, you an integrate VPD with APEX in many ways One option is to use the Virtual Private Database attribute of an APEX application to call a procedure that sets session context variables This technique works particularly well with legacy VPD applications that are already using session context variables Another option is to reference APEX items in the VPD policy,

which we will refer to as an item-based policy A third option is to use Oracle Database Global

Application Context variables, which were specifically designed for use with stateless applications Global Application Contexts have a significant drawback in that they offer no built-in way to purge expired sessions As such, they are not a good solution for APEX and VPD, and are not covered in this book

APEX Item-based Policy

The easiest approach to implement is to use APEX items As you might expect, this approach has both advantages and disadvantages

Following are the advantages of using APEX items:

APEX items are persistent for the life of the end user’s APEX session If you set the value

of an item when a user logs into the application, that value will still be there as long as the user is using the application

Because the items are persistent, their values need to be set only once—for example, when a user authenticates This is especially beneficial if the code used to determine

a user’s authorization rights is expensive

The syntax used to set an APEX item is exceptionally easy

APEX items are purged at regular intervals so a developer doesn’t need to worry about cleanup procedures

The disadvantage of using APEX items is that APEX items can be used only with APEX

applications If the VPD policy is to be used in a heterogeneous environment, it will need

separate logic for APEX and any other technology that needs to access the data

Trang 2

In the following example, we will create a simple table to store users and their roles When a user logs into our APEX application, we will store the role in an APEX item We will then reference the value of this APEX item in a function used for a VPD policy If the user’s role is ADMINISTRATOR,

he will see all rows in the table If his role is READ, he will see only his own row All others, such

as a user that access this table from a reporting tool, will not see any rows

SYS@AOS> grant create any context to sec_admin;

SYS@AOS> grant execute on sys.dbms_rls to sec_admin;

Execute the following DDL as schema SEC_ADMIN

create table sec_admin.user_app_roles(

id char(32),

user_name varchar2(255),

role_name varchar2(255),

constraint user_app_roles_pk primary key (id),

constraint user_app_roles_uq unique(user_name,role_name),

constraint user_app_roles_ck check (role_name in ('ADMINISTRATOR', 'READER')) )

/

create or replace

trigger bi_user_app_roles before insert on user_app_roles

for each row

begin

:new.id := sys_guid();

:new.user_name := upper(:new.user_name);

:new.role_name := upper(:new.role_name);

end;

/

insert into user_app_roles (user_name,role_name)

values ('DGRANT','ADMINISTRATOR');

insert into user_app_roles (user_name,role_name)

values ('JWHALEN','READER');

commit;

grant select on sec_admin.user_app_roles to sec_user;

create or replace function sec_admin.employees_apex_item_fn (

p_schema in varchar2 default null,

p_object in varchar2 default null)

return varchar2

as

l_return varchar2(255) := '1 = 2'; by default, this will return no rows l_role varchar2(255);

begin

A few basic tests to see if it looks like an APEX Session

Trang 3

and regexp_instr(sys_context('userenv','module'),

'^APEX:APPLICATION[[:space:]][0-9]+$') > 0 then

ROLE_NAME is an APEX Application Level Item Its value

is set using an APEX Application Process.

if v('ROLE_NAME') = 'ADMINISTRATOR' then

l_return := '1 = 1'; all rows

elsIf v('ROLE_NAME') = 'READER' then

l_return := 'email = v('' APP_USER'')'; only their own row else

l_return := '1 = 2'; no rows

end if;

end if;

return l_return;

end;

/

The following 2 drop statements will drop the policies used in both

examples from this section to make sure we have a clean slate.

begin

dbms_rls.drop_policy (object_schema => 'DATA_OWNER',

object_name => 'EMPLOYEES',

policy_name => 'EMPLOYEES_APEX_ITEM');

end;

/

begin

dbms_rls.drop_policy (object_schema => 'DATA_OWNER',

object_name => 'EMPLOYEES',

policy_name => 'EMPLOYEES_CONTEXT');

end;

/

begin

dbms_rls.add_policy

(object_schema => 'DATA_OWNER',

object_name => 'EMPLOYEES',

policy_name => 'EMPLOYEES_APEX_ITEM',

policy_function => 'EMPLOYEES_APEX_ITEM_FN');

end;

/

This function EMPLOYEES_APEX_ITEM_FN references an APEX item named ROLE_NAME.

Figure 12-11 shows the process that sets this item

Session Context-based Policy

The next example illustrates the use of a session context variable This technique is a more traditional approach to VPD and has an advantage in that it is applicable to other technologies such as Oracle Forms The main disadvantage of this technique when used with APEX is that the function used to set a user’s context is called on every page view If this function is expensive, it

could have a negative impact on performance However, if you are running Oracle Database 11g

Trang 4

or later, you can use the Function Result Cache feature to cache the results and greatly improve performance

create or replace context sec_admin.employees_context using set_employees_context /

create or replace procedure sec_admin.set_employees_context

as

begin

dbms_session.set_context('EMPLOYEES_CONTEXT','ROLE_NAME', null);

for c1 in (select role_name

from sec_admin.user_app_roles

where user_name = sys_context('userenv','client_info')) loop

dbms_session.set_context('EMPLOYEES_CONTEXT','ROLE_NAME', c1.role_name); end loop;

end;

FIGURE 12-11 Application level, before header process to set the role

Trang 5

grant execute on sec_admin.set_employees_context to sec_user;

create or replace function sec_admin.employees_context_fn (

p_schema in varchar2 default null,

p_object in varchar2 default null)

return varchar2

as

l_return varchar2(255) := '1 = 2'; by default, this will return no rows l_role varchar2(255);

begin

if sys_context('EMPLOYEES_CONTEXT','ROLE_NAME') = 'ADMINISTRATOR' then l_return := '1 = 1'; all rows

elsIf sys_context('EMPLOYEES_CONTEXT','ROLE_NAME') = 'READER' then

l_return := 'email = sys_context(''userenv'',''client_info'')'; only their own row

else

l_return := '1 = 2'; no rows

end if;

return l_return;

end;

/

The following 2 drop statements will drop the policies used in both

examples from this section to make sure we have a clean slate.

begin

dbms_rls.drop_policy (object_schema => 'DATA_OWNER',

object_name => 'EMPLOYEES',

policy_name => 'EMPLOYEES_APEX_ITEM');

end;

/

begin

dbms_rls.drop_policy (object_schema => 'DATA_OWNER',

object_name => 'EMPLOYEES',

policy_name => 'EMPLOYEES_CONTEXT');

end;

/

begin

dbms_rls.add_policy

(object_schema => 'DATA_OWNER',

object_name => 'EMPLOYEES',

policy_name => 'EMPLOYEES_CONTEXT',

policy_function => 'EMPLOYEES_CONTEXT_FN');

end;

/

APEX Components

Keeping in mind that each APEX page view is actually a new database session, you need to set this context with each page view APEX provides an application-level attribute designed for this exact purpose (shown in Figure 12-12), as it occurs very early in the APEX rendering code This is to ensure that the context is set before any application code that might need the context

is executed

Trang 6

Fine-grained Auditing

The balance between security and productivity is often tough to find Too much security, and people have a hard time doing their jobs Too little, and you expose your system to a security breach In many cases, developers are tasked with securing an existing or packaged application, which may limit their ability to change the underlying code or architecture FGA is a great candidate for these applications because it’s a relatively transparent, bolt-on solution to add

a layer of defense to your data

FGA allows a developer to construct an audit policy in PL/SQL and then apply that policy

to database tables Policies have access to all database environment variables of the end user’s

session, such as SYS_CONTEXT variables These environment variables allow you to define what

the signature of an application user should look like, and then trigger audit events for parameters

that fall outside of that signature For example, a FGA policy might check MODULE, ACTION, IP

ADDRESS, and time of day If any of these parameters fall outside those defined by your policy,

the audit event is triggered

As its name implies, this feature is only a way to audit events as they occur, but it won’t actually prevent access to the data Consequently, FGA should be used in conjunction with other security measures that actually protect the data Think of FGA as the silent alarm of an Oracle database As a silent alarm, it provides an interesting deterrent to valid users of an application Unlike techniques that hide data or raise an error, the psychological effect of this invisible tripwire can leave employees with the impression that if they start snooping around where they shouldn’t, they could initiate an investigation into their actions Think about this in the context of a bank robbery If a thief sets off a loud siren at night, he’ll simply run away However, the fear of triggering a silent alarm and walking out of the bank with bags full of money to a waiting

crowd of police officers provides a completely different psychological deterrent

FGA and APEX

APEX is exceptionally well suited to FGA As discussed in Chapter 11, APEX sets the environment

variables MODULE and ACTION to the APEX application number and page number To get an

FIGURE 12-12 VPD application attribute

Trang 7

idea of the environment variables available to you in an APEX session, navigate to the APEX SQL Workshop | SQL Commands section and run the following query (shown in Figure 12-13):

SELECT sys_context('USERENV', 'MODULE') module,

sys_context('USERENV', 'ACTION') action ,

sys_context('USERENV', 'CLIENT_IDENTIFIER') CLIENT_IDENTIFIER,

sys_context('USERENV', 'CLIENT_INFO') CLIENT_INFO,

v('APP_USER') app_user,

sys_context('USERENV', 'CURRENT_SCHEMA') CURRENT_SCHEMA,

sys_context('USERENV', 'SESSION_USER') SESSION_USER,

sys_context('USERENV', 'IP_ADDRESS') IP_ADDRESS

FROM dual;

In APEX version 3.2, the SQL Workshop is called Application 4500 and the SQL Commands feature is on page 1200 These numbers will obviously be different when you run the same query

in your actual application, but they provide a nice example since the APEX development

environment is also a collection of APEX applications Notice that CURRENT_SCHEMA is the

parsing schema for the query, as indicated by the select-list control in the upper-right corner of the page This variable represents the parsing schema of your application SESSION_USER will always

be the schema that the DAD uses to connect to the database Typically this is APEX_PUBLIC_

FIGURE 12-13 Context variable query in the SQL Workshop

Trang 8

USER for environments using Oracle HTTP Server or ANONYMOUS for environments using the

Embedded PL/SQL Gateway The IP_ADDRESS environment variable is the IP address of the

client Most people think this will be the IP address of the end user’s machine, but in an APEX environment, the database client is actually the Oracle HTTP server This concept is useful in the context of a FGA policy designed to allow only APEX access to the data as the IP address should always be the same However, if someone connects to the database directly with a tool such as SQL*Plus, that session’s IP address will be the IP address of the person’s PC, not the HTTP server

FGA Example 1

Now that you have a good idea of what FGA is, let’s work through a few examples that get progressively more complex For the following examples, we’ll use two schemas: SEC_USER and SEC_ADMIN SEC_USER will own the objects we want to audit, and SEC_ADMIN will own the functions and policies used in our auditing examples Before we can create any policies, we must connect as a DBA and grant SEC_ADMIN execute privileges on the DBMS_FGA package While we’re there, lets also grant select on the sys.dba_fga_audit_trail view to SEC_ADMIN

$ sqlplus / as sysdba

SQL> grant execute on dbms_fga to SEC_ADMIN;

Grant succeeded.

SQL> grant select on sys.dba_fga_audit_trail to sec_admin;

Grant succeeded.

The first example uses a function called IS_APEX_SESSION_ONE that simply checks to make sure the SESSION_USER environment variable is either APEX_PUBLIC_USER or ANONYMOUS, the two most common schemas used for APEX sessions If the SESSION_USER is considered valid,

the function returns a 1 (one), or else it returns a 0 (zero) Connect as the SEC_ADMIN user and

create the following function:

create or replace function is_apex_session_one

return number

authid definer

as

begin

if sys_context('userenv','session_user') in ('ANONYMOUS','APEX_PUBLIC_USER') then return 1;

else

return 0;

end if;

end is_apex_session_one;

/

Right now, this function is just a traditional function and is in no way associated with a FGA policy or a table Execute the following code as the SEC_ADMIN user to create the policy that will tie the previous function to the table we want to audit:

begin

dbmS_FGA.add_policy

(object_schema => 'SEC_USER',

Trang 9

policy_name => 'IS_FROM_APEX_POLICY',

audit_condition => 'SEC_ADMIN.IS_APEX_SESSION_ONE = 0',

audit_column => null,

statement_types => 'INSERT,UPDATE,DELETE,SELECT',

enable => true);

end;

/

In simple terms, an audit policy named IS_FROM_APEX_POLICY has been applied to the

SEC_USER.EMPLOYEES table This policy is enforced on all columns and all INSERT, UPDATE,

DELETE, and SELECT statements An audit event is triggered whenever the function IS_APEX_

SESSION_ONE returns a 0 (zero).

Since the goal of this policy is to audit any queries not originating from APEX, let’s first test this by querying the EMPLOYEES table from the APEX SQL Workshop The SQL Workshop is itself

an APEX application and thus falls within the allowed parameters of our policy

Executed in the Application Express SQL Workshop

select * from employees;

By querying the DBA_FGA_AUDIT_TRAIL, we can determine whether or not the previous query triggered an audit event:

SQL> select timestamp,db_user, client_id, object_schema,object_name,

policy_name, scn, sql_text from sys.dba_fga_audit_trail;

no rows selected

As expected, no audit event was logged Now, let’s run the same query once again from

SQL*Plus:

SQL> select * from employees;

Now connect as a privileged user and query the Audit Trail table:

SQL> select timestamp,db_user, policy_name, scn, sql_text from sys.dba_fga_audit_trail;

TIMESTAMP DB_USER POLICY_NAME SCN SQL_TEXT

- - - -

-08-MAR-09 SEC_USER IS_FROM_APEX_POLICY 4638186 select * from employees

FGA Example 2

For our next FGA example, we’ll leverage more session context information to narrow the

allowed parameters of the audit condition a bit This time, we will use MODULE to check that the query is coming from a specific APEX application We can also use the SYS_CONTEXT

function to determine the IP address of the client that issued the query In this case, the expected client is our HTTP server; any other IP address indicates the query might be coming from another client such as a SQL*Plus connection from an unauthorized workstation

create or replace

function is_apex_session_two

return number

authid definer

as

Trang 10

if sys_context('userenv','session_user') in ('ANONYMOUS','APEX_PUBLIC_USER') and sys_context('userenv','module') = 'APEX:APPLICATION 123'

and sys_context('userenv','ip_address') = '192.168.1.123'

then

return 1;

else

return 0;

end if;

end is_apex_session_two;

/

Before creating a new audit policy to associate this function with a table, we will drop the policy created in the preceding example:

BEGIN

DBMS_FGA.DROP_POLICY

(object_schema => 'SEC_USER',

object_name => 'EMPLOYEES',

policy_name => 'IS_FROM_APEX_POLICY');

END;

/

Now we can create a new policy for this function:

begin

dbmS_FGA.add_policy

(object_schema => 'SEC_USER',

object_name => 'EMPLOYEES',

policy_name => 'IS_FROM_APEX_POLICY_TWO',

audit_condition => 'SEC_ADMIN.IS_APEX_SESSION_TWO = 0',

audit_column => null,

statement_types => 'INSERT,UPDATE,DELETE,SELECT',

enable => true);

end;

/

As you will recall, the SQL Workshop is Application 4500 and our policy is checking to make sure the query is coming from Application 123 Querying the EMPLOYEES table from the SQL Workshop should trigger an audit event:

Executed in the Application Express SQL Workshop

select * from employees where 1 = 1;

I added the predicate 1 = 1 to show that the full SQL text is captured in the audit trail Now query

the audit trail to verify that a new event was logged:

SQL> select timestamp,db_user, client_id, scn, sql_text from sys.dba_fga_audit_trail;

DB_USER CLIENT_ID SCN SQL_TEXT

- - -

-SEC_USER 4638186 select * from employees

Ngày đăng: 06/07/2014, 23:20

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN