2013年4月20日 星期六

利用 Squid 代理伺服器(Proxy)分析 HTTPS 連線內容


筆者近來學了些如何側錄(sniffer) HTTPS 連線內容的技術,在這裡分享給大家。
要側錄 HTTPS 的封包並不困難,把 Wireshark 開催下去就好了(無誤),但要看到 HTTPS 封包的內容,就得想辦法解開加密內容,不然只能看到像下圖的有字天書。

HTTPS連線內容

對於 HTTPS 的加密方式,可參照非對稱式金鑰的介紹,因此若想要看見加密後的 HTTPS 封包內容,必須要利用金鑰(key)解開加密的內容。

以下圖為例,若我擷取到 A 傳給 B 的檔案,而該檔案是以 B 的公鑰(public key)加密,所以必須以 B 的私鑰(private key)進行解密後才能看到封包內容。

非對稱式金鑰加密

在HTTPS加密中,當使用者與伺服器連線時,會先取得伺服器的公鑰,並產生此次連線加密用的 對談鑰(Session key),接著用公鑰將對談鑰加密後回傳給伺服器,伺服器解開封包拿到對談鑰後,此次連線就以此組對談鑰進行加密連線。

因此若要解開伺服器公鑰加密的內容,需要伺服器的私鑰以進行解密之外,我們還需要能將封包內容與私鑰作解密運算的工具,所幸 Wireshark 已經提供這樣的功能,可以協助我們對 HTTPS 封包進行解密,我們只需要把伺服器的私鑰匯入即可,Wireshark 會解開使用者與伺服器連線時交換的對談鑰,並將 SSL 加密內容都解開。

在 Wireshark 工具頁面選擇 [Edit] > [Preferences] > [Protocols] > [SSL] ,在 [RSA keys lits] 的地方按下 [Edit],輸入伺服器的相對應資訊就好,需要注意的是 Protocol 需要填入[HTTP],代表解密出來的是 HTTP 協定

Wireshark的SSL解密

進行至此,就欠缺如何取得伺服器的私鑰了!

如何取得伺服器的私鑰?
筆者的作法是:
以 Squid 代理伺服器(proxy server)的 SSL-bump 功能截斷 HTTPS 的連線,再匯入代理伺服器的私鑰即可。(意即私鑰來自代理伺服器)

如下圖所示,將原先使用者與伺服器間的加密連線變成透過代理伺服器,且因為代理伺服器的 SSL-bump 功能,所以原先使用者的 HTTPS 連線變成會以代理伺服器的公鑰加密,而由代理伺服器到伺服器間的連線才是以伺服器的公鑰加密,因此只需在代理伺服器上側錄封包,再以代理伺服器的私鑰進行解密即可。

正常HTTPS連線與Squid with SSL-bump的連線差異

以下是實作過程。
首先安裝 Squid 代理伺服器,不過在 Debian 中以 apt-get 安裝的 Squid 是沒有 SSL-bump功能的,因此可以用兩種方式進行安裝:

  1. 下載 Squid 原始碼自行編譯、安裝
  2. 以 apt-get source 抓下 Squid 套件原始碼,進行重新編譯

筆者選擇第二種,以下是筆者的編譯過程:
準備編譯環境:
sudo apt-get install devscripts build-essential libssl-dev
sudo apt-get build-dep squid3

建立資料夾,下載原始碼後進行解壓縮
cd /usr/src; sudo mkdir squid3; cd squid3
sudo apt-get source squid3
cd squid3-3.1.19

修改編譯時的選項,約第40行左右,加入 --enable-ssl, --with-openssl=/usr/include/openssl 兩個選項
sudo vim debian/rules
# 約40行,加入以下選項
#     --enable-ssl
#     --with-openssl=/usr/include/openssl
sudo debuild -us -uc
sudo dpkg -i the_deb_file

安裝完成之後,編輯 Squid 的設定檔
vim /etc/squid3/squid.conf:
加入以下設定:
ssl_bump allow all
always_direct allow all
http_port 3128 sslBump cert=/path/to/cert.pem key=/path/to/key.pem

上述設定檔的意思為:
http_port 指定使用通訊埠 3128,並啟用 sslBump 功能,以及 CA 與金鑰的位置。

接下來,要產生代理伺服器的CA與金鑰(公, 私),最基本的就是以 openssl 指令製作,但程序比較複雜,而 OWASP Project 整理了一個 Shell script 可以協助快速產生 CA 與金鑰,可以到以下連結下載:
https://github.com/OWASP/OWASP-WebScarab/blob/master/doc/cert.sh

使用的方式非常簡單,先編輯該 Shell script 內的相關設定,再執行以下指令:
sh cert.sh the_domain_of_server
上述指令就可產生 CA 與金鑰。
由於筆者的代理伺服器 IP 是192.168.0.254,因此筆者使用以下指令產生 CA 與金鑰:
sh cert.sh 192.168.0.254
指令執行完後,在同目錄下會產生一個 sslcerts 的資料夾,以及192.168.0.254.p12憑證檔,其中較為重要的檔案為:
server的私鑰檔案: sslcerts/private/192.168.0.254-key.pem
server的CA: sslcerts/192.168.0.254-cert.pem

再將之前的 squid.conf 檔案中將 CA 與金鑰的路徑位置設定完整並重新啟動 Squid3 即可。

最後,在使用者端的瀏覽器部分,代理伺服器設定要特別設定加密連線。
以IE為例,要按下進階進行設定,在筆者環境中,HTTP 和 Secure 都設定代理伺服器的IP以及通訊埠 3128,如下圖所示。

瀏覽器的Proxy設定

以上設定完成後,就可開始利用 Wireshark 進行實驗。

解密前

解密後

從上述的比較,可以發現側錄 HTTPS 封包後,已經可以看到封包內含的使用者所進行的 GET 行為。
若要觀看完整的加密後的連線內容,還可按下右鍵,選擇 [Follow SSL Stream]




這樣就能把原本的無字天書都解開了 :P
Great!

沒有留言: