EBS VPD介绍和使用实例

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没有数据的问题,以及类似的问题。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值