MySQL協議分析(2)

MySQL協議分析(2)

此階段是在壓縮傳輸無加密條件下進行的協議分析python

思路

結合Oracle官網的說明和本身用wireshark加python進行數據包分析mysql

步驟

  1. 客戶端與服務器端是否壓縮的協商階段sql

  2. 壓縮傳輸的數據包格式數據庫

  3. 數據包解壓縮分析過程服務器

壓縮協商階段

  • 首先,用戶發起鏈接數據庫的請求,並添加了壓縮的參數-C進行傳輸,此時在網絡中TCP創建後,服務器端會給客戶端一個Greeting,其中包括了服務器端的MySQL版本、協議版本、支持的能力(其中就包括是否支持壓縮)等。網絡

  • 而後,客戶端會發送給服務器端一個登錄請求,其中包括:能力標誌(裏面包括了是否要進行壓縮傳輸,如果壓縮傳輸,則標誌位置爲1)、字符集、用戶名、密碼(md5加密)等。加密

數據包以下:3d

MySQL Protocol
    Packet Length: 58
    Packet Number: 1
    Login Request
        Client Capabilities: 0xa6a5
            .... .... .... ...1 = Long Password: Set
            .... .... .... ..0. = Found Rows: Not set
            .... .... .... .1.. = Long Column Flags: Set
            .... .... .... 0... = Connect With Database: Not set
            .... .... ...0 .... = Don't Allow database.table.column: Not set
            .... .... ..1. .... = Can use compression protocol: Set
            .... .... .0.. .... = ODBC Client: Not set
            .... .... 1... .... = Can Use LOAD DATA LOCAL: Set
            .... ...0 .... .... = Ignore Spaces before '(': Not set
            .... ..1. .... .... = Speaks 4.1 protocol (new flag): Set
            .... .1.. .... .... = Interactive Client: Set
            .... 0... .... .... = Switch to SSL after handshake: Not set
            ...0 .... .... .... = Ignore sigpipes: Not set
            ..1. .... .... .... = Knows about transactions: Set
            .0.. .... .... .... = Speaks 4.1 protocol (old flag): Not set
            1... .... .... .... = Can do 4.1 authentication: Set
        Extended Client Capabilities: 0x0003
        MAX Packet: 1073741824
        Charset: utf8 COLLATE utf8_general_ci (33)
        Username: root
        Password: 3dad2597af36922c753c7ef0d0f22c18ee0af0bf

具體的能力標誌位以下:code

共16位,值爲0xa6a5,即1010011010100101,其中,第11位的 Can use compression protocol: Set就是是否壓縮,若爲1,則壓縮傳輸,若爲0,則不壓縮。ip

  • 服務器端發送確認,開始壓縮傳輸,規則見下面的壓縮傳輸的數據包格式。

壓縮傳輸的數據包格式說明

壓縮數據包主要分爲壓縮數據包頭和壓縮後的數據包(或者未壓縮的數據包,這種狀況在後面說明)

壓縮數據包頭

壓縮數據包頭共佔7字節,分爲3段,格式以下:

第一段: 壓縮後的mysql數據包的長度。它的值的計算方法是TCP總數據包的長度-7,也就是總長度減去壓縮數據包頭剩下的就是mysql數據包壓縮後的長度,佔3字節;

第二段: sequence id,序列id,佔1字節;

第三段: 壓縮前/解壓縮後的mysql數據包的長度,佔3字節。

壓縮傳輸的數據包

分爲兩種狀況:

第一種狀況是數據包長度小於50字節,這種狀況下即便選擇了壓縮傳輸,因爲數據包過短,兼顧效率問題,就不會被壓縮傳輸;同時在上述的壓縮數據包頭的第三個字段會爲0.

第二種狀況是數據包長度大於50字節,這種狀況下就會對數據包進行壓縮傳輸,且壓縮數據包頭的第三個字段會大於0.

解壓縮

在官網中說明了壓縮過程選用的是zlib進行的壓縮,因此咱們須要找到zlib的解壓縮方法。本次採用的是Python中的zlib庫。

  • 請求的壓縮

(從客戶端發起一個SQL語句的請求,保證此請求的長度大於50bytes,會產生壓縮)

執行SQL語句以下:

select ID,USERID,USERNAME,BIRTHDAY,SALARY from smalltable where ID = 999 and USERNAME = 'fdsfsdfdsdsafs'

在wireshark中抓到這次請求的包,右鍵,複製爲轉移字符串,而後粘貼到Python中,定義一個字符串s。

import zlib

s = "\x78\x9c\xcb\x64\x60\x60\x60\x2e\x4e\xcd\x49\x4d\x2e\x51\xf0\x74\xd1\x09\x0d\x76\x0d\x82\x52\x7e\x8e\xbe\xae\x3a\x4e\x9e\x41\x21\x1e\x2e\x8e\x91\x3a\xc1\x8e\x3e\x8e\x41\x91\x0a\x69\x45\xf9\xb9\x0a\xc5\xb9\x89\x39\x39\x25\x89\x49\x39\xa9\x0a\xe5\x19\xa9\x45\xa9\x40\x8d\x0a\xb6\x0a\x96\x96\x96\x0a\x89\x79\x29\x0a\x30\xbd\x40\x21\xf5\xb4\x94\xe2\xb4\xe2\x14\x20\x99\x52\x9c\x98\x56\xac\x0e\x00\xcd\x25\x21\x24"

un_c  = zlib.decompress(s)
print un_c

觀察到輸出爲iselect ID,USERID,USERNAME,BIRTHDAY,SALARY from smalltable where ID = 999 and USERNAME = 'fdsfsdfdsdsafs'

驗證了分析過程的正確性。

問題:在語句前有一個字符'i',猜想可能爲校驗碼之類的值,未驗證。

  • 響應的壓縮

(從客戶端發起個SQL語句的請求,保證獲得的響應結果大於50bytes,且大於1514,大於1514是爲了驗證當響應結果特別長,發生了分包時的狀況)

執行SQL語句

select * from smalltable where ID < 100

相似於上面的步驟,將全部響應的TCP包中的TCP payload右鍵,複製爲轉義字符串,粘貼到Python中,經過這種方式手動把多個包拼在一塊兒。(由於這個包太長了,這裏就不放了)程序也與上面相同。驗證後正確解壓縮,只是結果與咱們查看的結果的格式有些許的不一樣。

壓縮無加密的MySQL協議分析結束。

相關文章
相關標籤/搜索