天天看點

Oracle TNS 314 協定分析:三、連接配接認證流程與包分析Connect 流程特殊資料定義擷取協定版本暨協定頭解析擷取連接配接字元串及用戶端資訊網絡參數交換(deadbeef)Secure Network Service擷取驗證參數​​​​​​​擷取Oracle版本号

Connect 流程

Client Server
1 ------- Connect(01) -----> 擷取連接配接字元串
2 <----- 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包示例

Oracle TNS 314 協定分析:三、連接配接認證流程與包分析Connect 流程特殊資料定義擷取協定版本暨協定頭解析擷取連接配接字元串及用戶端資訊網絡參數交換(deadbeef)Secure Network Service擷取驗證參數​​​​​​​擷取Oracle版本号

代碼示例

從此包中解析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

包示例

Oracle TNS 314 協定分析:三、連接配接認證流程與包分析Connect 流程特殊資料定義擷取協定版本暨協定頭解析擷取連接配接字元串及用戶端資訊網絡參數交換(deadbeef)Secure Network Service擷取驗證參數​​​​​​​擷取Oracle版本号

示例代碼

擷取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標頭

包解析示例

Oracle TNS 314 協定分析:三、連接配接認證流程與包分析Connect 流程特殊資料定義擷取協定版本暨協定頭解析擷取連接配接字元串及用戶端資訊網絡參數交換(deadbeef)Secure Network Service擷取驗證參數​​​​​​​擷取Oracle版本号

擷取驗證參數

通過解析包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

​​​​​​​包示例

Oracle TNS 314 協定分析:三、連接配接認證流程與包分析Connect 流程特殊資料定義擷取協定版本暨協定頭解析擷取連接配接字元串及用戶端資訊網絡參數交換(deadbeef)Secure Network Service擷取驗證參數​​​​​​​擷取Oracle版本号

代碼示例

擷取使用者名

--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包,内容不詳

​​​​​​​包示例

Oracle TNS 314 協定分析:三、連接配接認證流程與包分析Connect 流程特殊資料定義擷取協定版本暨協定頭解析擷取連接配接字元串及用戶端資訊網絡參數交換(deadbeef)Secure Network Service擷取驗證參數​​​​​​​擷取Oracle版本号

​​​​​​​代碼示例

--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