您的位置:首页 > 其它

EBS VPD介绍和使用实例

2016-11-30 00:36 295 查看

VPD介绍

什么是VPD(虚拟专用数据库):

VPD is one feature that allows development community to enforce security by attaching a security policy to database objects such as tables, views and synonyms.

简单的说,VPD就是向特定的数据库对象附加一个安全策略,在对这个对象操作的过程在中,会自动的使用这个安全策略进行验证,同时满足自定义条件和安全策略的操作才会获得预期的结果。下面以一个故事来介绍VPD:

在一个交友网站上,有一张表ALL_PERSON_INFO存放该网站所有帅哥靓女的信息,该表有一个字段gender来存放该记录的性别。当一个用户登录该网站时,系统会有一个session值记录当前用户的性别。同时为了防止该网站背上同性恋之家的黑名,于是站长就来了一条严重的限制,该网站的用户只能查看到异性的信息。当一位名叫Tea的帅哥登录到这个网站,需要查找名字中带有coffee的女性时,常有的查询语句是:

Select * from
ALL_PERSON_INFO  api
where  api. Gender <>session( ‘gender’)
and api.name like = ‘%coffee%’


很好,该语句查到的永远都是用户的异性信息。

但一个电脑牛人gay却想去看该系统的帅哥信息,他获取到这条查询语句后,使用SQL注入的技术(或其他技术)在该SQL查询上添加了另外一个条件,然后变成如下语句:

Select * from
ALL_PERSON_INFO  api
where  api. Gender <>session( ‘gender’)
and api.name like = ‘%coffee%’or api. Gender = session( ‘gender’)


这样造成的结果就是该网站所有的帅哥信息,赤裸裸地被这个gay拿去和他的同类们分享。

于是该网站的站长就气愤地找他们的DBA,说他没有把数据保护好,这下可苦了这个DBA,但却是也不是他的错啊,话虽如此,但系统优化还是得继续。这个DBA开始了他的优化系统之路,通过多方查找,他将视线定位在了VPD上,使用该技术,他成功根除了这个安全隐患。他的基本步骤概括如下:

首先将session( ‘gender’)放到一个APPLICATION CONTEXT中,然后为该表建立了一个同义词GENDER_PERSON_INFO,然后在该同义词上设置了一项安全策略该策略具有一个相关函数,称为policy function,它返回一个用作谓词的字符串api. Gender <>sys_context(‘friend’,’gender’),通过使用该策略,凡是含有api. Gender = session( ‘gender’)的查询将不会返回任何结果。

VPD使用实例

建立对象和数据

CREATE TABLE hss.vpd_test(
ID NUMBER,
NAME VARCHAR2(100),
gender CHAR(1)
);


INSERT INTO hss.vpd_test VALUES(1,'hansen','M');
INSERT INTO hss.vpd_test VALUES(2,'tea','M');
INSERT INTO hss.vpd_test VALUES(3,'tiger','F');
INSERT INTO hss.vpd_test VALUES(4,'coffee','F');
COMMIT;


查询数据如下:



在APPS下建立同义词

CREATE SYNONYM HX_VPD_TEST For hss.vpd_test;


查询结果如下:



建立应用程序上下文

CREATE CONTEXT HX_VPD USING apps.XXHX_VPD_PKG;


查询结果如下:



建立策略函数包和应用设置函数包,包头定义如下

CREATE OR REPLACE PACKAGE XXHX_VPD_PKG IS
/*==================================================
Program Name:
XXHX_VPD_PKG
Description:
该pakcage的功能是建立策略函数gender_valid,
设置应用程序上下文值

History:
1.00  2016-11-28  Jane   Creation
==================================================*/

/*==================================================
Function Name :
gender_valid
Description:
安全策略函数必须带2个参数:第1个参数是方案名
(或用户名)、第2个参数是方案对象名(或表名、
视图名)。该函数返回附加到SQL语句的where子句
后面的字符串.即使在安全策略函数中不使用也要带
上所述2个参数,否则在执行时会出现“ORA-28112:
无法执行策略函数”的错误提示。
Argument:
obj_schame  方案名
obj_name    方案对象名
Return
安全策略字符串
History:
1.00  2016-11-28  Jane    Creation
==================================================*/
FUNCTION gender_valid(obj_schame VARCHAR2,
obj_name   VARCHAR2) RETURN VARCHAR2;

/*==================================================
Function Name :
set_context
Description:
该方法用于设置应用程序上下文的值
Argument:
p_user_gender 性别
History:
1.00  2016-11-28  Jane    Creation
==================================================*/
PROCEDURE set_context(p_user_gender VARCHAR2);
END xxhx_vpd_pkg;


注册为对象注册策略

BEGIN
DBMS_Rls.Add_Policy( object_schema   =>'APPS',
object_name  =>'HX_VPD_TEST',
policy_name  =>'HX_VPD_GENDER',
function_schema => 'APPS',
policy_function =>'XXHX_VPD_PKG.GENDER_VALID',
policy_type => DBMS_RLS.SHARED_CONTEXT_SENSITIVE);

END;


查看结果:



查看策略函数返回的条件



查看使用策略后查看F的结果



查看使用策略后,性别为 M的 结果



但当我们开一个新窗口,再查询的时候就没有结果



MOAC中VPD的使用

查看策略函数

SELECT *
FROM dba_policies DBA
WHERE dba.object_name = 'PO_HEADERS';


结果:



结果分析:

从该结果中可以得到策略函数是MO_GLOBAL.ORG_SECURITY;

查看可能涉及的Application Context:

SELECT *
FROM dba_context dc
WHERE package = 'MO_GLOBAL'


结果:



结果分析:

从该结果中可以得到在MO_GLOBAL.中使用了两个Application Context,但我们不能肯定都是我们需要的,需要进入MO_GLOBAL.ORG_SECURITY函数中检查;

MO_GLOBAL.ORG_SECURITY分析

FUNCTION org_security(obj_schema VARCHAR2,
obj_name   VARCHAR2) RETURN VARCHAR2 IS
l_ci_debug fnd_profile_option_values.profile_option_value%TYPE := NULL;
BEGIN
--
--  Returns different predicates based on the access_mode
--  The codes for access_mode are
--  M - Multiple OU Access
--  A - All OU Access
--  S - Single OU Access
--  Null - Backward Compatibility - CLIENT_INFO case    --
--  The Predicates will be appended to Multi-Org synonyms
IF obj_name = 'AR_PAYMENT_SCHEDULES' AND g_access_mode = 'S' THEN
RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'') OR (org_id = -3116)';
ELSIF g_access_mode IS NOT NULL THEN
IF g_access_mode = 'M' THEN
RETURN 'EXISTS (SELECT 1
FROM mo_glob_org_access_tmp oa
WHERE oa.organization_id = org_id)';
ELSIF g_access_mode IN ('A', 'B') THEN
RETURN 'org_id <> -3113'; -- Bug5109430 filter seed data from policy predicate
ELSIF g_access_mode = 'S' THEN
RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'')';
ELSIF g_access_mode = 'X' THEN
RETURN '1 = 2';
END IF;
ELSE
-- This section is used reserved for debugging using CLIENT_INFO
-- Interim solution for MFG teams
fnd_profile.get('FND_MO_INIT_CI_DEBUG',
l_ci_debug);
IF l_ci_debug = 'Y' THEN
RETURN 'org_id = substrb(userenv(''CLIENT_INFO''),1,10)';
ELSE
RETURN '1=2';
END IF;
END IF;
END org_security;


分析:

第一个条件

IF obj_name = 'AR_PAYMENT_SCHEDULES' AND g_access_mode = 'S' THEN
RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'') OR (org_id = -3116)';


关于对象AR_PAYMENT_SCHEDULES,在dba_policies表中查看策略函数是GLOBAL.ORG_SECURITY_GLOBAL,对于该方法有段注释This is a restricted policy function to support global data -3116.所以这个条件可以忽略。

第二个条件

IF g_access_mode = 'M' THEN
RETURN 'EXISTS (SELECT 1
FROM mo_glob_org_access_tmp oa
WHERE oa.organization_id = org_id)';


这个条件就是实现多ou的判断条件,如果当前的访问模式是’M’,并且数据的org_id也在session表mo_glob_org_access_tmp中,那么这条数据是安全的。

第三个条件

ELSIF g_access_mode IN ('A', 'B') THEN
RETURN 'org_id <> -3113'; -- Bug5109430 filter seed data from policy predicate


该 Bug 不是公众可访问的 Bug (未公开)“这是我在metalink上查找Bug5109430的信息,不过有注释表明access _Mode=A是预留到将来使用,我估计access _Mode=B也是为了将来使用。

第四个条件

ELSIF g_access_mode = 'S' THEN
RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'')';


第五个条件

ELSIF g_access_mode = 'X' THEN
RETURN '1 = 2';


返回nothing 不知道有什么用。

接下来使用了一个预制文件’FND_MO_INIT_CI_DEBUG’,我们可以查到他的用处:“MO:设置 Client_Info 以进行调试它的说明是“此配置文件仅限 Oracle 用于调试用途。”

在上面的分析中,我们得出该系统使用了临时表mo_glob_org_access_tmp和上下文sys_context(”multi_org2”,”current_org_id”)的值。也明白了PO_HEADRES查询不到数据的原因,可能是mo_glob_org_access_tmp和上下文sys_context(”multi_org2”,”current_org_id”)的值为空。

初始化环境:

我们知道mo_global.set_policy_context可以设置环境的初始化,如果能将这些理解,完全能够解决PO_HEADERS没有数据的问题,以及类似的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ebs MOAC VPD