大家好,我是hihttps,專注SSL web安全研究,今天本文就是教大家怎樣從wireshark源碼中,提取旁路https解密的源碼,非常值得學習和商業應用。
一、旁路https解密條件
眾所周知,都知道wireshark中設置一定的條件,可以解密出https的通信成明文。
https是加密傳輸的,旁路一般情況是無法解密的,但為什么服務器和客戶端可以解密成明文呢,那就是雙方都有密鑰。所以旁路https解密的條件是:
1、知道服務端的私鑰。(如RSA靜態密鑰配置)
2、知道客戶端瀏覽器的密鑰。(如chrome的開發者模式會把密鑰存到文件)
如何知道和設置密鑰,請大家在百度搜索相關文章。如https://blog.csdn.net/wangyiyungw/article/details/82178339
二、wireshark對SSL解密密鑰計算流程
1、通過抓包Client端Hello和Server端Hello報文得到兩邊隨機數client_random和server_random。
2、客戶端將permaster 通過Sever端證書公鑰密鑰加密后,發送給服務器,Server用私鑰的解密得到解密后的permaster。
3、Client端和Server端分別根據client_random、server_random和permaster_secret生成master secret就是能解密正常報文。
三、代碼查找
首先在wireshark官網下載源碼,解壓到本地硬盤,進入...\epan\dissectors目錄,搜索帶有“ssl”關鍵字的.c文件,找到packet-ssl-utils.c和packet-ssl.c,核心的解密算法全部在packet-ssl-utils.c這個文件里面。哈哈,加密解密雖然復雜,但wireshark用了libgcrypt這個庫,事半功倍,我們來欣賞一下核心函數。
1、packet-ssl-utils.h幾個重要的結構體,用來存儲SSL會話相關解密信息。
/* SSL 對話信息結構體 */
typedef struct _SslDecryptSession {
guchar _master_secret[SSL_MASTER_SECRET_LENGTH]; //非常重要的解密密鑰
guchar _session_id[256]; //sesstion id
guchar _client_random[32]; //客戶端隨機數
guchar _server_random[32];//服務端隨機數
StringInfo session_id;//session id 用於ssl/tls 快速握手,不必每次計算密鑰
StringInfo session_ticket;//session ticket,用於ssl/tls 快速握手,不必每次計算密鑰
StringInfo server_random;//服務端隨機數
StringInfo client_random;//客戶端及隨機數
StringInfo master_secret;//主解密密鑰
StringInfo handshake_data;//握手報文
/* the data store for this StringInfo must be allocated explicitly with a capture lifetime scope */
StringInfo pre_master_secret;//pre_master_secret
guchar _server_data_for_iv[24];//服務端解密向量
StringInfo server_data_for_iv;
guchar _client_data_for_iv[24];//可客戶端解密向量
StringInfo client_data_for_iv;
gint state;//狀態
const SslCipherSuite *cipher_suite;//加密套件
SslDecoder *server;//服務端解密結構體指針
SslDecoder *client;//肯定解密結構體指針
SslDecoder *server_new;
SslDecoder *client_new;
#if defined(HAVE_LIBGNUTLS)
gcry_sexp_t private_key;
#endif
StringInfo psk;
StringInfo app_data_segment;
SslSession session;
gboolean has_early_data;
} SslDecryptSession;
2、packet-ssl-utils.c里面的幾個重要的函數:
//HMAC消息摘要信息計算
ssl_hmac/md_init(SSL_HMAC* md, const void * key, gint len, gint algo)
ssl_hmac/md_update(SSL_HMAC* md, const void* data, gint len)
ssl_hmac/md_final(SSL_HMAC* md, guchar* data, guint* datalen)
ssl_hmac/md_cleanup(SSL_HMAC* md)
// sha/md5計算
ssl_sha/md5_init(SSL_SHA_CTX* md)
ssl_sha/md5_update(SSL_SHA_CTX* md, guchar* data, gint len)
ssl_sha/md5_final(guchar* buf, SSL_SHA_CTX* md)
ssl_sha/md5_cleanup(SSL_SHA_CTX* md)
//加載解密私鑰和證書
ssl_private_decrypt(const guint len, guchar* data, gcry_sexp_t pk)
ssl_load_keyfile(const gchar *ssl_keylog_filename, FILE **keylog_file,
const ssl_master_key_map_t *mk_map)
//驗證HMAC和計算偽隨機數
tls_hash(StringInfo *secret, StringInfo *seed, gint md,
StringInfo *out, guint out_len)
tls12_prf(gint md, StringInfo* secret, const gchar* usage,
StringInfo* rnd1, StringInfo* rnd2, StringInfo* out, guint out_len)
//計算pre_master_secret
ssl_generate_pre_master_secret(SslDecryptSession *ssl_session,
guint32 length, tvbuff_t *tvb, guint32 offset,
const gchar *ssl_psk,
const ssl_master_key_map_t *mk_map)
//計算master_secret
ssl_generate_keyring_material(SslDecryptSession*ssl_session)
.........
3、解密核心入口函數,輸入密文,輸出明文
ssl_decrypt_record(SslDecryptSession *ssl, SslDecoder *decoder, guint8 ct, guint16 record_version,
gboolean ignore_mac_failed,
const guchar *in, guint16 inl, StringInfo *comp_str, StringInfo *out_str, guint *outl)
{
tls_decrypt_aead_record...
ssl_cipher_suite_dig...
ssl_cipher_decrypt...
tls_check_mac...
}
代碼很長,就不貼出來來,大家自行去下wireshark源碼吧,全部的解密過程都在packet-ssl-utils.c這個文件中。
總體說來:旁路解密https涉及到密碼學的很多東西,沒這方面的基礎,看不懂也很正常。好在有很多開源大神貢獻了源碼,我們只需要復制拷貝,掌握關鍵的函數入口,就可以成功抽絲剝繭,把核心的源碼剝離出來了,有需要的可以訪問https://github.com/qq4108863聯系獲取。
所以如果任意一方泄漏了密鑰,HTTPS也是不安全的,並不能阻止被攻擊。如果有網站,可以在github上下載一個SSL web應用防火牆,如hihttps是開源免費的。