Oracle TNS 314 協議分析——三、鏈接認證流程與包分析

Connect 流程

Clientpython

 

 

 

Server數據庫

1windows

-------網絡

Connect(01)session

----->oracle

獲取鏈接字符串app

2ui

<-----spa

Resend指針

-------

 

3

-------

Connect(01)

----->

 

4

<-----

Accept

-------

獲取協議Version 

5

-------

Data NetworkService(deadbeef)

----->

網絡參數交換

6

<-----

Data NetworkService(deadbeef)

-------

 

7

-------

Data SetProtocal(01)

----->

 

8

<-----

Data SetProtocal(01)

-------

 

9

-------

Data SetDataTypes(02)

----->

 

10

<-----

Data SetDataTypes(02)

-------

 

11

-------

Data UOCIFun(03) GetSessionKey(76)

----->

 

12

<-----

Data OPIParam(08)  with 3 params

Sessionkey,verifydata,,dbid

-------

 

13

-------

Data UOCIFun(03) Generic Auth call(73)

----->

獲取驗證參數:用戶名,密碼在此傳輸

Username sessionkey pass

14

<-----

Data OPIParam(08) with 40 params

-------

認證結果包含

AuthDBName;dbid:AuthUserID;SessionID

15

-------

Data Piggyback(11) session switch(6b)

----->

 

16

<-----

Data OPIParam(08)

-------

Oracle版本號

 

認證錯誤時從14包日後,會返回一個marker,而後客戶端會發送一個請求marker,接着服務端返回錯誤信息,此過程詳細參見錯誤信息返回這個章節

特殊數據定義

在分析32位和64位客戶端時,能夠注意到不一樣版本客戶端再解析上出現64位feffffffffffffff和00000000000000 在32位狀況下分別都被代換爲01和00的狀況,因此咱們定義

feMagic,在32位時爲0x01 64位下爲0xfe ff ff ff ff ff ff ff

00Magic,在32位時爲0x00 64位下爲0x00 00 00 00 00 00 00 00

獲取協議版本暨協議頭解析

Connect 的Accept包是獲取TNS版本號的最佳地點,Connect過程會協商版本號,Connect過程當中,client會傳輸本身支持的版本號,服務端會結合本身的狀況,最終在Accept中選定一個版本號。Accept包的Package Type爲2

Accept包格式

 

32bit

64bit

 

Version

2

2

版本號

Service Option

2

2

Bit標誌選項

Session Data Unit Size

2

2

一個DataUnit最多多大,在傳輸超長包時,Data 包會被拆解成如此大小的包

Max Transmition Unit Size

2

2

最大Data長度

Value Of 1

2

2

指定了服務端的Endian類型

Accept Data Length

2

2

 

Accept Data Offset

2

2

指向Accept data的指針,通常直接指向結尾(包含TNS頭)

Connect Flag0

1

1

標誌位

Connect Flag1

1

1

標誌位

Unknown

8 or 17

8 or 17

未知,通常前8字節爲0

Service Option:

    ..0. .... .... .... = Broken Connect Notify

    ...0 .... .... .... = Packet Checksum

    .... 0... .... .... = Header Checksum

    .... .0.. .... .... = Full Duplex

    .... ..0. .... .... = Half Duplex

    .... ...0 .... .... = Don't Care

    .... .... 0... .... = Don't Care

    .... .... ...0 .... = Direct IO to Transpor

    .... .... .... 0... = Attention Processing

    .... .... .... .0.. = Can Receive Attention

    .... .... .... ..0. = Can Send Attention

Connect Flag0 and flag1

    ...0 .... = NA services required

    .... 0... = NA services linked in

    .... .0.. = NA services enabled

    .... ..0. = Interchange is involved

    .... ...0 = NA services wanted

 

Accept包示例

代碼示例

今後包中解析TNS version

--02 get tns version if(data:byte(3)==2) then tnsVersion=string.unpack(">I2",data:sub(7)) print("tnsVersion:"..tnsVersion) end

獲取鏈接字符串及客戶端信息

經過解析包Connect包能夠得到鏈接字符串,進而獲取客戶端的詳細信息,包含客戶端程序,當前用戶,windows版本等。

 

Connect包格式

 

32bit

64bit

 

Version

2

2

版本號

Compatible Version

2 2 兼容最低版本

Service Options

2

2

Bit標誌選項

Session Data Unit Size

2

2

一個DataUnit最多多大,在傳輸超長包時,Data 包會被拆解成如此大小的包

Max Transmition Unit Size

2

2

最大Data長度

NT Protocol Characteristics

2

2

網絡參數

Line Turn Around Value

2

2

 

Value 1

2

2

指定了本地的Endian類型

Length of Connect Data

2

2

鏈接字符串長度

Offset of Connect Data

2

2

鏈接字符串從TNS頭算的偏移量

Max Receivable Connect Data

4

4

 

Connection Flag0

1 1  

Connection Flag1

1 1  

Trace Across Facility item1

4 4  
Trace Across Facility item2 4 4  

Trace Unique Connection ID

8 8  

unknown

8 or 20 8 or 20  

Service Options,Connection Flag 同Accept

NT Protocol Characteristics:
    0... .... .... .... = Hangon to listener connect
    .0.. .... .... .... = Confirmed release
    ..0. .... .... .... = TDU based IO
    ...0 .... .... .... = Spawner running
    .... 0... .... .... = Data test
    .... .0.. .... .... = Callback IO supported
    .... ..0. .... .... = ASync IO Supported
    .... ...0 .... .... = Packet oriented IO
    .... .... 0... .... = Can grant connection to another
    .... .... .0.. .... = Can handoff connection to another
    .... .... ..0. .... = Generate SIGIO signal
    .... .... ...0 .... = Generate SIGPIPE signal
    .... .... .... 0... = Generate SIGURG signal
    .... .... .... .0.. = Urgent IO supported
    .... .... .... ..0. = Full duplex IO supported
    .... .... .... ...0 = Test operation

包示例

示例代碼

獲取TNS版本及鏈接字符串

if(data:byte(3)==1) then tnsVersion=string.unpack(">I2",data,7) print("requestTnsVersion:"..tnsVersion) local connectDataLength=string.unpack(">I2",data,23) local connectDataOffset=string.unpack(">I2",data,25) print("connect string:"..string.unpack("c"..connectDataLength,data,connectDataOffset-2)) end

網絡參數交換(deadbeef)Secure Network Service

經過解析包 Data  Network Service 包能夠得到網絡相關參數好比servie version,其意義暫不明確,注意此包是data包,下面示例數據沒有帶data包頭

包解析示例

獲取驗證參數

經過解析包dataid 03 callid 73能夠得到用戶名,密碼hash等不少信息

包格式

 

32bit

64bit

 

序列號

1

1

 

可變字節

16 or 20

44 or 48

 

用戶名長度

1

1

 

用戶名

上字節決定

上字節決定

 

Keyvalue pairs

變長

變長

sessionkey及密碼等數據

可變頭

注意到使用不一樣客戶端鏈接不一樣數據庫,數據包到用戶名這裏的偏移量不一樣(可能緣由,oracle版本,不一樣的客戶端)

Sqlplus11 to oracle12c

Navicat to oracle11 

 

32位Navicat

fe ff ff ff ff ff ff ff

18 00 00 00 01 01 00 00

fe ff ff ff ff ff ff ff

12 00 00 00 00 00 00 00

fe ff ff ff ff ff ff ff

fe ff ff ff ff ff ff ff

fe ff ff ff ff ff ff ff

0f 00 00 00 01 01 00 00

fe ff ff ff ff ff ff ff

12 00 00 00

fe ff ff ff ff ff ff ff

fe ff ff ff ff ff ff ff

 

01

0f 00 00 00 01 01 00 00

01

13 00 00 00

01

01

一個在序號後有44個字節,一個48個字節,具體處理能夠先跳過44個字節看是否ff,若是是跳到48個字節

32位狀況相似,只是將feMagic變爲01,因此也有兩種狀況16或20個字節

​​​​​​​Keyvalue對

對灰色頭部如下內容除直接跟的用戶名外,所有以keyvalue形式存在。

Key和value間存在固定4字節未知字段,keyvalue對之間存在8字節未知字段。

Key和value均以長度開頭,長度fe表示變長,fe後續一個字節的長度byte並以00結尾如sessionid的值。

下面以上面的包爲例進行解析:

用戶名:scott

0863232373636f7474

4字節未知字段

24000000

AUTH_SESSKEY

0c415554485f534553534b4559

4字節未知字段

20010000

value

fe403346334137413241324636443935363537434643383241304439314141383033354334334532413932313746424334384437313935343137323638374442414120423145303544373245443630413239333636454331334131444232423941303500

8字節未知字段

100000027000000

AUTH_PASSWORD

0d415554485f50415353574f5244

4字節未知字段

c0000000

value

4042353343343732314336334342323537334244423535383936364541364630363844353834423034364134313945373146463430444444363537464343343742

...

...

...

...

...

...

8字節未知字段

0000000030000000

AUTH_FAILOVER_ID

10415554485f4641494c4f5645525f4944

8字節未知字段

0000000000000000

 

​​​​​​​包示例

代碼示例

獲取用戶名

--060307 get username if(data:byte(3)==6 and data:byte(9)==3 and data:byte(10)==0x73) then local userNamePos --test client 32bit or 64bit if(data:byte(12)~=0xfe)then is64Bit=false end if(is64Bit) then print("64bit:true") else print("64bit:false") end if(is64Bit) then if(data:byte(9+2+1+43)==0xff)then userNamePos=9+2+1+44 end if(data:byte(9+2+1+47)==0xff)then userNamePos=9+2+1+48 end else if(data:byte(9+2+1+15)==0xff)then userNamePos=9+2+1+16 end if(data:byte(9+2+1+21)==0xff)then userNamePos=9+2+1+20 end end if(userNamePos) then local username=string.unpack("s1",data,userNamePos) print("username:"..username) ngx.ctx.username=username end end

​​​​​​​獲取Oracle版本號

在鏈接完成以後,客戶端會發起data 116b包,內部後續一個data DB Version(033b)請求,ThinClient 下會直接發起data 033b,請求oracle版本,版本號以data 08包形式返回,解析其返回包能夠得到Oracle版本號。注意返回的data 08 包不止在這裏使用,不少命令的返回都使用此包,此種包有這樣幾種形式,

08後直接後續字段:如版本號包

08後後續返回字段數,再接續字段:好比認證結果返回

獲取版本包格式以下

 

32bit

64bit

 

unused

2

2

ThinDriver 此處爲1

Banner Length

1

1

版本字符串長度

Banner

上字節決定

上字節決定

Oracle版本字符串

版本號

4

4

版本int表示,little endian,minor版本號和build號分別用第二個字節的高低4bit表示

變長結尾 變長 變長 多是1702包也多是0901包,內容不詳

​​​​​​​包示例

​​​​​​​代碼示例

--06033b oracle version request if(data:byte(3)==6 and data:byte(9)==3 and data:byte(10)==0x3b) then cHeaderPos=9 end --start to process db version request if(cHeaderPos>1 and data:byte(cHeaderPos)==3 and data:byte(cHeaderPos+1)==0x3b) then requestOracleVersion=true end --06089a get oracle version if(data:byte(3)==6 and requestOracleVersion) then local versionString,p=string.unpack("s1",data,12) print("oracleVersion:"..versionString) local minor oracleVersion.fix,oracleVersion.subbuild,minor,oracleVersion.major=string.unpack("BBBB",data,p) oracleVersion.minor=minor/16 oracleVersion.build=minor%16 print(oracleVersion.major..'.'..oracleVersion.minor..'.'..oracleVersion.build..'.'..oracleVersion.subbuild..'.'..oracleVersion.fix) requestOracleVersion=false end
相關文章
相關標籤/搜索