zoukankan      html  css  js  c++  java
  • Oracle TNS 314 协议分析——3、连接认证流程与包分析

    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包示例

    代码示例

    从此包中解析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
  • 相关阅读:
    java中awt和swing是的关系以及区别
    java 5.0和java6.0的区别
    bpel 经典实例入门教程
    java中指针的问题
    linux下软件的基本安装和卸载
    stomp与veil用法
    in perspective用法
    不錯的句子
    fit into用法
    ceremony用法
  • 原文地址:https://www.cnblogs.com/yizhu2000/p/12866531.html
Copyright © 2011-2022 走看看