昨天我們實測了將帳號密碼放在網址 (GET 請求) 中的極度危險性。許多剛入門的開發者會有一種迷思:「既然 GET 會把參數暴露在網址列上,那我改用 POST 請求,把資料藏在封包的『身體 (Body)』裡面,別人看不見網址不就安全了嗎?」
今天,我們要無情地打破這個迷思。我們將繼續使用 Wireshark 攔截 HTTP POST 請求,看看如果沒有 HTTPS 的保護,藏在 Body 裡的秘密是否真的能瞞天過海。
我們一樣使用 httpbin.org 來模擬一次網站的表單登入行為。這次我們改用 POST 方法,將帳號密碼當作表單資料傳送。
【實作練習】
http 顯示過濾器並開始擷取。curl -X POST -d "username=admin&password=SuperSecretBodyPassword" http://httpbin.org/post

畫面解析:
從終端機的回應中,我們可以看到資料這次不是出現在 args (網址參數) 中,而是出現在 form (表單) 欄位裡。背後的 Wireshark 也成功捕捉到了一個 POST /post HTTP/1.1 的封包,並且標示了它的資料格式為 application/x-www-form-urlencoded(這是一般網頁表單預設的傳輸格式)。
在瀏覽器或終端機介面上,這串密碼確實不會顯示在網址列。但到了網路底層,它究竟長什麼樣子呢?
【實作練習】
停止抓包後,點選剛剛那行 POST 封包。在中間的詳細資訊窗格,層層展開 Hypertext Transfer Protocol,並找到最下方的 HTML Form URL Encoded 節點將其展開。

畫面解析:
迷思正式破滅!Wireshark 非常聰明地自動解析了封包的 Body 內容。Form item: "username" = "admin" 與 Form item: "password" = "SuperSecretBodyPassword" 完完整整、一字不漏地以純文字明碼顯示在這裡。就算你沒有把它寫在網址上,只要是未加密的 HTTP 通訊,資料在網路上依然形同裸奔。
為了更徹底了解 HTTP POST 的結構,我們再次召喚 Wireshark 的殺手級功能,看看它在網線中傳遞的最原始面貌。
【實作練習】
對著 POST 封包按右鍵,選擇 「Follow (追蹤)」 -> 「TCP Stream (TCP 串流)」。

畫面解析:
觀察紅色字體的客戶端請求,這就是標準 HTTP POST 協定的實體結構:
POST /post、User-Agent、以及非常重要的 Content-Length: 47(告訴伺服器接下來的身體有多長)。username=admin&password=SuperSecretBodyPassword。今天我們透過實戰證明了一個重要的資安觀念:「POST 並沒有比 GET 更安全」。
POST 只是改變了資料放置的位置(從網址移到了 Body),但只要外層沒有加密,對攔截封包的駭客來說,兩者的獲取難度完全是零。
連續兩天看穿了 HTTP 明碼傳輸的危險性後,你一定會問:「那我們平常上網輸入信用卡號、登入網銀,難道也這麼危險嗎?」
當然不是!明天 [Day 18],我們將正式跨入現代網路安全的基石:HTTPS 與 TLS 加密協定,帶你看看加密後的封包在 Wireshark 裡究竟長什麼樣子!我們明天見。