Mysql 協定嗅探是什麼

一个新手
發布: 2017-10-13 10:14:40
原創
1656 人瀏覽過

需求

監聽透過網路卡的所有mysql流量,進行解析,可在不影響現有業務情況下,進行入侵偵測(IDS)或資料整合

協定要點

起初發現用mysql-front存取資料庫和mysql 的客戶端存取時資料包格式不同,糾結很久,不明白,mysql-front源碼看了眼,delphi,不懂,棄

壓縮解析

當連結mysql時,若啟用-C參數表示,對於連接資料啟用壓縮,壓縮格式為zlib

mysql的壓縮函數為:

// mysql-source/mysys/my_compress.c

my_bool my_compress(uchar *packet, size_t *len, size_t *complen)
{
  DBUG_ENTER("my_compress");
  if (*len < MIN_COMPRESS_LENGTH)
  {
    *complen=0;
    DBUG_PRINT("note",("Packet too short: Not compressed"));
  }
  else
  {
    uchar *compbuf=my_compress_alloc(packet,len,complen);
    if (!compbuf)
      DBUG_RETURN(*complen ? 0 : 1);
    memcpy(packet,compbuf,*len);
    my_free(compbuf);
  }
  DBUG_RETURN(0);
}


uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen)
{
  uchar *compbuf;
  uLongf tmp_complen;
  int res;
  *complen=  *len * 120 / 100 + 12;

  if (!(compbuf= (uchar *) my_malloc(key_memory_my_compress_alloc,
                                     *complen, MYF(MY_WME))))
    return 0;                    /* Not enough memory */

  tmp_complen= (uint) *complen;
  res= compress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet, (uLong) *len);
  *complen=    tmp_complen;

  if (res != Z_OK)
  {
    my_free(compbuf);
    return 0;
  }

  if (*complen >= *len)
  {
    *complen= 0;
    my_free(compbuf);
    DBUG_PRINT("note",("Packet got longer on compression; Not compressed"));
    return 0;
  }
  /* Store length of compressed packet in *len */
  swap_variables(size_t, *len, *complen);
  return compbuf;
}
登入後複製

 其中第35行呼叫了zlib中的compress()函數,但是該處僅對compress()進行了封裝,並沒有協定解析部分,我們繼續往下看。

整個專案尋找目標程式碼比較費勁,可以先在頭檔中尋找關鍵訊息,於是找到了下面的程式碼

// mysql-source/include/sql_state.h
{ ER_NET_UNCOMPRESS_ERROR                 ,"08S01", "" }
登入後複製

這是在mysql在解析壓縮的資料時如果出錯的提示訊息和錯誤碼,依序可以找到其引用,發現了真正的封包壓縮代碼

// mysql-source/sql/net_serv.cc

static uchar *
compress_packet(NET *net, const uchar *packet, size_t *length)
{
  uchar *compr_packet;
  size_t compr_length;
  const uint header_length= NET_HEADER_SIZE + COMP_HEADER_SIZE;

  compr_packet= (uchar *) my_malloc(key_memory_NET_compress_packet,
                                    *length + header_length, MYF(MY_WME));

  if (compr_packet == NULL)
    return NULL;

  memcpy(compr_packet + header_length, packet, *length);

  /* Compress the encapsulated packet. */
  if (my_compress(compr_packet + header_length, length, &compr_length))
  {
    /*
      If the length of the compressed packet is larger than the
      original packet, the original packet is sent uncompressed.
    */
    compr_length= 0;
  }

  /* Length of the compressed (original) packet. */
  int3store(&compr_packet[NET_HEADER_SIZE], static_cast<uint>(compr_length));
  /* Length of this packet. */
  int3store(compr_packet, static_cast<uint>(*length));
  /* Packet number. */
  compr_packet[3]= (uchar) (net->compress_pkt_nr++);

  *length+= header_length;

  return compr_packet;
}
登入後複製

 從8-19行可以看到,壓縮資料的組包過程,前面分別加了 NET_HEADER_SIZE + COMP_HEADER_SIZE 長的控製字段

查找該宏,發現其定義如下

1 // mysql-source/include/mysql_com.h
2 
3   /* Constants when using compression */
4 #define NET_HEADER_SIZE 4        /* standard header size */
5 #define COMP_HEADER_SIZE 3        /* compression header extra size */
登入後複製

NET_HEADER_SIZE 字段中長度字段存儲資料部分未解壓縮時的長度

# COMP_HEADER_SIZE 欄位是用來儲存 解壓縮後的資料的長度,我們可以依序申請內存,然後呼叫zlib對壓縮內容進行解析即可。

 如果不分析直接進行對wireshark抓到的資料進行zlib解析的話,由於控製字段的存在會解壓縮失敗,在python中的報錯如下

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>zlib.error: Error -3 while decompressing data: incorrect data check
登入後複製

 起初看到這個錯誤很頭痛也不想看zlib解析細節,才有了從mysql找原因的本文,現在可以記錄zlib 壓縮字串的開頭常常是\x78\x9c,出現同樣錯誤的可以看看是否正確

以上是Mysql 協定嗅探是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板